一、变量定义
1.1 Var定义变量
var name string = "zhangsan"
var age int = 21
var isOk bool bool
1.2 类型推导变量定义
在函数内部,可以使用更简略的 := 方式声明并初始化变量
// 变量名 := 表达式
n := 10
var age = 18
1.3 一次定义多个变量
package main
import "fmt"
func main() {
var username, sex string
username = "张三"
sex = "男"
fmt.Println(username, sex)
}
1.4 批量声明变量
package main
import "fmt"
func main() {
var (
a string
b int
c bool
)
a = "张三"
b = 10
c = true
fmt.Println(a, b, c)
}
二、常量定义
2.1 常量
声明了 pi 和 e 这两个常量之后,在整个程序运行期间它们的值都不能再发生变化了
const pi = 3.1415
const e = 2.7182
// 多个常量也可以一起声明
const (
pi = 3.1415
e = 2.7182
)
2.2 同时声明多个变量
const (
n1 = 100
n2
n3
)
// 上面示例中,常量 n1、n2、n3 的值都是 100
三、Fmt包
3.1 Println
一次输入多个值的时候
Println中间有空格Println会自动换行,Print不会
fmt.Println("zhangsan", "lisi", "wangwu") // zhangsan lisi wangwu
3.2 Print
一次输入多个值的时候
Print没有 中间有空格Print不会自动换行
fmt.Print("zhangsan", "lisi", "wangwu") // zhangsanlisiwangwu
3.3 Printf
Printf是格式化输出,在很多场景下比Println更方便
fmt.Printf("%s 今年 %d 岁", name, age) // zhangsan 今年 20 岁 }
3.4 Sprintf
fmt.Sprintf 函数用于将格式化的字符串和其他值组合成一个新的字符串。与 Printf 不同,Sprintf 不会直接输出结果,而是将结果返回为一个新的字符串。
name := fmt.Sprintf("%v", "你好")
fmt.Println(name)
四、Init函数与main函数
4.1 init函数
go语言中 init函数用于包 (package) 的初始化,主要特征如下:
init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等每个包可以拥有多个
init函数包的每个源文件也可以拥有多个
init函数不同包的
init函数按照包导入的依赖关系决定该初始化函数的执行顺序init函数不能被其他函数调用,而是在main函数执行之前,自动被调用
4.1.1 包的执行顺序
全局声明 ——> init() ——> main()
4.2 main函数
Go语言程序的默认入口函数(主函数):func main(),函数体用{}一对括号包裹
func main(){
//函数体
}
4.3 init对比main函数
相同点
两个函数在定义时不能有任何的参数和返回值,且Go程序自动调用。
不同点
init可以应用于任意包中,且可以重复定义多个。main函数只能用于main包中,且只能定义一个。对同一个
go文件的init()调用顺序是从上到下的。对同一个
package中不同文件是按文件名字符串比较从小到大顺序调用各文件中的init()函数。对于不同的
package,如果不相互依赖的话,按照main包中"先import的后调用"的顺序调用其包中的init()`如果
package存在依赖,则先调用最早被依赖的package中的init(),最后调用main函数。
四、命名规范
Go是一门区分大小写的语言。命名规则涉及变量、常量、全局函数、结构、接口、方法等的命名。
任何需要对外暴露的名字必须以大写字母开头,不需要对外暴露的则应该以小写字母开头。当命名(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Analysize,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的public);命名如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的private)
4.1 文件命名
尽量采取有意义的文件名,简短,有意义,应该为小写单词,使用下划线分隔各个单词。例如:create_user.go
4.2 结构体命名
采用驼峰命名法,首字母根据访问控制大写或者小写struct 申明和初始化格式采用多行,例如下面:
type MainConfig struct {
Port string `json:"port"`
Address string `json:"address"`
}
4.3 变量命名
变量名称一般遵循驼峰法,首字母根据访问控制原则大写或者小写
可访问的变量命名:User,Port
内部访问的变量:user,port
4.4 常量命名
常量命名通常采用全部大写的方式,并使用下划线分隔单词,以表示其常量的性质。例如:MAX_VALUE、MIN_LIMIT等。
4.5 函数命名
函数命名一般采用驼峰法,首字母根据访问控制原则大写或者小写。例如:GetData、ProcessData等。
4.6 接口命名
接口命名与函数命名类似,采用驼峰法。首字母根据访问控制原则大写或者小写,例如:DataProvider、DataProcessor等。
4.7 包命名
包的命名应该采用简短且有意义的名称,通常使用小写字母。例如:utils、database等。
五、defer函数
5.1 defer运用及思想
defer语句采用的设计思想是后进先出(LIFO, Last In First Out)的栈式结构,也就是说,最后声明的defer语句会最先执行
关键字
defer用于注册延迟调用这些调用直到
return前才被执。因此,可以用来做资源清理多个
defer语句,按先进后出的方式执行,谁离return近谁先执行defer语句中的变量,在defer声明时就决定了
package main
import "fmt"
func Func() {
defer fmt.Println("defer2")
fmt.Println("func")
defer fmt.Println("defer1")
}
func main() {
defer fmt.Println("defer4")
Func()
defer fmt.Println("defer3")
}
执行顺序
func
defer1
defer2
defer3
defer4
5.2 defer坑点
deferi修改返回值,如果是返回值带名字的则defer时能够修改成功,当不带名字时defer返回不成功
package main
import "fmt"
func DeferRuturn() int {
a := 0
defer func() {
a = 1
}()
return a
}
func DeferRuturn2() (a int) {
a = 0
defer func() {
a = 1
}()
return a
}
func main() {
fmt.Println(DeferRuturn()) // 0
fmt.Println(DeferRuturn2()) // 1
}