内容简介:写给大忙人看的Golang教程(一)阅读本文之前,我认为你已经掌握其他语言基础并写出一个简单的项目。
Tips
写给大忙人看的Golang教程(一)
阅读本文之前,我认为你已经掌握其他语言基础并写出一个简单的项目。
(1)Golang编程注意事项
.go main()
(2)Golang中的常用转义字符
\t \n \\ \" \r
(3)注释方式
// 注释内容 /* 注释内容 */
(4)Golang的代码规范
- 尽量使用行注释注释整个方法或语句
- 使用Tab缩进
- 使用
gofmt -w
格式化代码 - 运算符两侧加空格
-
Golang的代码风格:
// HelloWorld.go package main import "fmt" func main() { fmt.Println("Hello World") }
- 一行代码最好不要超过80个字符
(5)官方编程指南
- Go的官方网站 https://golang.org
- Go的标准库英文官方文档 https://golang.org/pkgdoc
- Go的标准库中文官方文档 https://studygolang.com/pkgdoc
(6)变量
- 使用
var
关键字定义变量:var 变量名称 数据类型
- 使用类型推导:
var 变量名称 = 值
- 省略
var
关键字:变量名称 := 值
, 变量名称不应该是已经定义过的 -
变量名称 := 值
等同于var 变量名称 数据类型 = 值
- 多变量声明:
var 变量名称, 变量名称... 数据类型
- 多变量赋值:
var 变量名称, 变量名称, ... = 值, 值, ...
- 省略
var
关键字多变量声明和赋值:变量名称, 变量名称, ... := 值, 值, ...
- 声明全局变量:
var ( 变量名称 = 值 ... )
(7)Golang支持的数据类型
-
使用
unsafe.Sizeof()
查看变量占用的空间package main import ( "fmt" "unsafe" ) func main() { var x int = 10 fmt.Println("The x size: ", unsafe.Sizeof(x)) // The x size: 8 }
-
float32
表示单精度,float64
表示双精度 -
字符常量使用单引号
-
Go中的字符编码使用
UTF-8
类型 -
bool
类型只能取true
或false
-
在Go中字符串是不可变的
-
Go支持使用反引号输出原生字符串
- 字符串拼接使用加号时最后一个加号需要保留在行尾
(8)基本数据类型转换
- 数值类型互相转换:
目标数据类型(变量)
。 - 数值与字符串互转:
- 数字转字符串:使用
fmt.Sprintf()
字符串格式化函数。 - 数字转字符串:使用
strconv.FormatBool()
、strconv.FormatInt()
、strconv.FormatUint()
、strconv.FormatFloat()
格式化函数。 - 字符串转数字:使用
strconv.ParseBool()
、strconv.ParseInt()
、strconv.ParseUint()
、strconv.ParseFloat()
格式化函数。
- 数字转字符串:使用
(9)指针数据类型
package main import "fmt" func main() { var i = 10 var ptr *int = &i fmt.Println("变量i的内存地址是: ", ptr) // 变量i的内存地址是: 0xc00004a080 fmt.Println("变量i的存储内容是: ", *ptr) // 变量i的存储内容是: 10 }
(10) 值类型与引用类型
- 值类型通常存放到栈区。
- 引用类型通常存放在堆区,栈中有堆中的引用。
(11)Golang中的标识符
_
(12)运算符
- Golang中只有
x++
和x--
,没有++x
和--x
- 自增自减运算值独立的语句,不允许类似的:
x := a++
(13)控制台输入输出
fmt.Sacnf() fmt.Sacnln()
(14) 原码、反码、补码
- 计算机中0表示正数,1表示负数
- 计算机中都是用补码进行运算的,因为CPU只会加法运算
- 正数的原、反、补都是相同的
- 负数的反码是原码符号位不变其他位取反
- 负数的补码是反码加1
- 0的原、反、补相同
(15)流程控制
(15.1)顺序控制
略
(15.2) 分支控制
-
if
语句:if x>12 { } // Golang支持直接在condition中定义变量 if x:=12; x>12 { }
-
if-else
语句:if x:=12; x>20 { }else { }
-
if-else if-else
语句:if x:=12; x>100 { }else if x>50 { }else if x>10 { }else { }
-
switch-case-default
语句:// 每个分支不需要break语句 // switch也支持在condition中直接定义变量 // case支持多个表达式 // 取消break使用fallthrough语句————switch穿透 switch y:=10;y { case 5: // something case 10: // something fallthrough case 20, 25, 30: // something default: // something }
(15.3)循环控制
-
for
循环for i:=1;i<10;i++ { } // Golang也提供了for-each或for-range类似的循环 str := "Hello Golang." for index, value:=range str { // index表示索引 // value表示值 }
-
while
循环for { if condition { break } // something }
-
do-while
循环for { // something if condition { break } }
(16) 随机数
// 设置随机数的种子为当前的系统时间 rand.Seed(time.Now().Unix()) // 生成0-99范围的随机数 randomNumber := rand.Intn(100)
(17)break、continue、goto、return语句
-
break
语句在多层嵌套中可以通过标签指明要终止到哪一层语句块:
label: for { break label }
-
continue
语句在多层嵌套中可以通过标签指明要跳出到到哪一层语句块:
label: for { continue label }
-
goto
语句可以无条件跳转,容易造成逻辑混乱,一般不主张使用goto
语句:label: for { goto label }
-
return
语句用户退出函数return // 或 return some
(18)函数
-
函数基本语法:
func functionName (paramsList) (returnList) {}
-
Golang不支持函数重载
-
Golang函数本身也是一种数据类型,可以赋值给变量,那么该变量也是函数类型
-
Golang函数可以作为实参传入另一个函数
-
Golang支持自定义数据类型,使用:
type 自定义数据类型名 数据类型
type myfunc func(int)(int, int)
-
支持使用
_
忽略返回值 -
支持可变参数
package main import "fmt" func main() { ret := sum(1, 2, 3) fmt.Println(ret) //6 } // 可变参数 func sum(args...int) int { sum := 0 for i:=0; i<len(args); i++ { sum += args[i] } return sum }
(19)包
包的本质就是一个目录,Go的每一个文件都必须属于一个包。
-
打包:
package packageName
-
导入包:
import "packageName" // 导入多个包 import ( "packageName" ... ) // 导入包时自动从GOPATH下面的src下面引入
-
包支持别名
package main import f "fmt" func main() { f.Println() }
(20) init
函数
- 在Go中每一个源文件都可以有一个
init
函数,它优先于main
函数执行,被Go框架调用。
func init() {}
- 先执行引入的包中的
init
函数再执行main
包中的init
函数
// util.HelloWorld.go package utils import "fmt" func init() { fmt.Println("Util.HelloWorld() init") } func HelloWorld()(){ fmt.Println("Hello World") } // main.test.go package main import ( "StudyGo/utils" "fmt" ) func init() { fmt.Println("Main.main() init") } func main() { utils.HelloWorld() } // Util.HelloWorld() init // Main.main() init // Hello World
(21)匿名函数
-
直接调用
func (paramsList)(returnList){ // something }()
-
赋值给一个变量
x := func (paramsList)(returnList){ // something } y := x(paramsList)
(22)闭包
-
闭包就是函数与其相关的引用环境构成的实体
package main import ( "fmt" "strings" ) func main() { fileName := "file" fileSuffix := ".mp3" ms := makeSuffix(fileSuffix) ret := ms(fileName) fmt.Println(ret) } func makeSuffix(suffix string) func(string) string { return func (s string) string { if strings.HasSuffix(s, suffix) { return s }else { return s + suffix } } }
(23)defer 关键字
-
defer是Go语言中的延时机制,用于处理关闭文件句柄等资源释放操作
package main import "fmt" func main() { SayHello() } func SayHello() { defer fmt.Println("Bye.") fmt.Println("Hi.") } // Hi. // Bye.
- 使用defer修饰的语句会压入栈中,其相关的值也会被压入栈中
(24) 字符串函数
len() strconv.Atoi(s string) (i int, err error) strconv.Itoa(i int) string strconv.FormatInt(i int64, base int) string strings.Contains(s string, sub string) bool strings.Count(s string, sub string) int strings.EqualFold(s_0 string, s_1 string) bool strings.Index(s string, sub string) int strings.LastIndex(s string, sub string) string.Replace(s string, oldSub string, newSub string, n int) string string.ToLower(s string) string.ToUpper(s string) string.Split(s string, sep string) array string.TrimSpace(s string) string string.Trim(s string, sub string) string string.TrimLeft(s string, sub string) string string.TrimRight(s string, sub string) string string.HasPrefix(s string, sub string) bool string.HasSuffix(s string, sub string) bool
(25)时间日期函数
-
time.Time
:表示时间类型 -
time.Now() struct
:获取当前本地时间 -
time.Now().Year()
:返回年 -
time.Now().Month()
:返回月,使用int(time.Now().Month())
取得数字 -
time.Now().Day()
:返回日 -
time.Now().Hour()
:返回时 -
time.Now().Minute()
:返回分 -
time.Now().Second()
:返回秒 -
time.Now().Format(s string)
:格式化时间数据,2006-01-02 15:04:05
表示格式化的格式字符串其中的值不能改变 -
time.Sleep(d Duration)
:休眠函数time.Hour time.Minute time.Second time.Millisecond time.Microsecond time.Nanosecon
-
time.Now().Unix() int64
:返回Unix秒时间戳 -
time.Now().UnixNano() int64
:返回Unix纳秒时间戳
(26)内置函数
len() new() make()
(27)错误处理
-
在Go中捕获异常的机制是使用
defer
关键字修饰匿名函数,导致匿名函数最后执行,在匿名函数中调用recover()
函数,通过返回值是否为nill
来判断是否发生异常信息。package main import "fmt" func main() { ret := ComputeNumber(1, 0) fmt.Println(ret) } func ComputeNumber(n_0 int, n_1 int) int { defer func() { if e := recover(); e != nil{ fmt.Println(e) } }() result := n_0 / n_1 return result }
-
自定义错误
使用
errors.New(Type) *Type
创建一个error
类型,panic()
接收一个空接口类型,输出错误信息并结束运行。package main import "errors" func main() { err := readConfigureFile("config.json") if err !=nil { panic(err) // panic: Read config.ini error. } } func readConfigureFile(path string)(err error) { if path != "config.ini" { return errors.New("Read config.ini error.") } else { return nil } }
(28)数组
在Go中数据是值类型,使用以下方式创建数组。
var 数组名称 [元素个数]数据类型 = [元素个数]数据类型{元素} var 数组名称 = [元素个数]数据类型{元素} var 数组名称 = [...]数据类型{元素个数} var 数组名称 = [...]数据类型{索引:值} for-each/for-range
(29)slice 切片
数组的长度是固定的,切片 的长度不是固定的。
-
var 切片名称 []数据类型
-
切片名称[索引:索引]
-
切片的结构:
[起始数据元素指针, 长度, 容量]
-
通过make创建切片:
var 切片名称 []数据类型 = make([]数据类型, 长度, 容量)
-
切片支持普通遍历和
for-range
方式遍历 -
使用
append()
函数追加元素到切片末尾,容量不够时自动扩容 -
使用
copy()
函数拷贝数组 -
string
类型底层是个byte
数组,也可以进行切片处理。string
是不可变的,如果要修改字符串,需要先将字符串转换为切片修改完成后再转换成为字符串。
str := "Hello World." arr := []byte(str) arr[11] = '!' str = string(arr) fmt.Println(str)
(28)Map映射
- Map是一种键值对数据结构,声明方式如下:
var Map名称 map[KeyType]ValueType
-
使用
make(map[KeyType]ValueType)
分配空间 -
delete(m map[Type]Type, key Type)
:通过Key删除元素,如果元素不存在也不会报错 -
清空Map一种是遍历删除,一种是
make
重新分配空间,使得原来的Map成为垃圾让GC回收 -
查找使用
value, ok = mapName[Key]
,如果ok
为true
,表示元素存在 - Map支持
for-range
遍历
for key, value := range mapName{ }
- Map支持切片
-
(28)OOP
-
Go中的OOP是通过
struct
来实现的type 类名 struct { 属性名 数据类型 ... }
-
创建结构体变量
var 变量名称 结构体类型 var 变量名称 结构体类型 = 结构体类型{} 变量名称 := 结构体类型{} // 下面两种写法等价: var 变量名称 *结构体名称 = new(结构体名称) var 变量名称 *结构体名称 = &结构体名称 // 在操作属性、方法的时候Go进行了优化,下面两种写法是等价的: (*变量名称).属性 = 值 变量名称.属性 = 值
-
每一个字段可以加上一个tag,该tag可以通过反射机制获取,常见的场景就是序列化与反序列化
属性名称 数据类型 `json:Tag名称`
-
Go中的类没有构造函数,通常通过工厂模式来实现
package model // 如果Name和Age改为name和age,需要为person绑定Getter和Setter方法 type person struct { Name string `json:"name"` Age int `json:"age"` } func NewPerson(n string, a int)(*person){ return &person{ Name : n, Age : a, } }
package main import "fmt" import "StudyGo/model" func main() { var tom = model.NewPerson("Tom", 20) fmt.Println((*tom).Name) fmt.Println((*tom).Age) }
-
在Go中在一个结构体中嵌套另一个匿名结构体就认为实现了继承
type Ani struct { name string age int } type Cat struct { Ani say string }
结构体变量.数据类型 = 值
-
接口
type 接口名称 interface { 方法名称(参数列表)(返回值列表) }
- 接口不允许包含任何变量
- Go中的接口不需要显式实现,只要一个变量含有接口的所有方法,那么就实现了这个接口
-
类型断言
- 当一个类型转换为了接口类型在转换为该类型时需要使用类型断言判断是否可以转换为该类型
var number float32 var x interface{} x = t t = x.(float32) // 判断一下是否可以转换成为float32类型
(29)方法
func (recv type) funcName (paramsList)(returnList) { // something }
-
recv
表示这个方法与type
类进行绑定,方法内通过recv
操作type
类中的字段 -
type
是个结构体类型 -
recv
是个结构体类型变量
通常为了执行效率一般不会直接传入结构体类型作为接收器,而是结构体类型指针:
func (dog *Dog) function()(){ // 绑定的是地址,操作时也要使用地址 // something } // 调用时 var d Dog (&d).function()
但是编译器做出了相关的优化:
var d Dog d.function()
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Visual C# 2008入门经典
James Foxall / 张劼 / 人民邮电出版社 / 2009-6 / 39.00元
《Visual C#2008入门经典》分为五部分,共24章。第一部分介绍了Visual C# 2008速成版开发环境,引导读者熟练使用该IDE;第二部分探讨如何创建应用程序界面,包含窗体和各种控件的用法;第三部分介绍了编程技术,包括编写和调用方法、处理数值、字符串和日期、决策和循环结构、代码调试、类和对象的创建以及图形绘制等;第四部分阐述了文件和注册表的处理、数据库的使用和自动化其他应用程序等;第......一起来看看 《Visual C# 2008入门经典》 这本书的介绍吧!