一、命名
1.命名规则
a.一个名字必须以一个字母(Unicode字母)或者下划线开头。
b.后面可以跟任意数量的字母,数字,下划线。
c.区分大小写
2.不可用于自定义名字的25个关键字
break default func i nterface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var
3.30多个预定义的名字
内建常量: true false iota nil 内建类型: int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64 complex128 complex64 bool byte rune string error 内建函数:make len cap new append copy close delete complex real imag panic recover
a.内部预订名字不是关键字
b.可以再定义,重新使用它们
c.一般不要定义它们,除非在一些特殊的场景里。(什么场景能使用,我也想不到。反正少用就对了)
4.作用域
a.如果一个名字是在函数内部定义,那么他就只在函数内部有效。
b.如果在函数外部定义,那么将在当前包的所有文件夹中都可以访问。
c.如果一个名字是大写字母开头的(必须是在函数外部定义的包级名字;包级函数名本身也是包级名字),那么他是可以导出的,也就是说可以被外部的包访问。
d.包本身的名字一般总用小写字母。
5.命名方式
go语言推荐使用驼峰命名方式
二、声明
1.声明语句的意义,以及go语言的四种主要类型
a.声明语句定义了程序的各种实体对象以及部分或全部属性
b.四种类型:
变量:var
常量:const
类型:type
函数:func
2.一个例子简单介绍下各个声明的部分
package main //导入声明 import ( "fmt" ) //常量声明,包一级范围声明。可以再整个包中的每个源文件中使用 const boilingF = 212.0 //函数声明,无返回值,无参数的函数申明 func main() { //变量声明,函数级声明,只能在函数中使用 bool1 :=true if bool1{ fmt.Println("this value is true") }else { fmt.Println("this value is fales") } c := test(1) fmt.Println(c) } //带参数和返回值的函数声明,无返回值省略 返回值类型 一项。但是哪怕没有参数,也不可省略(参数)这一项。 // func 函数名(参数)返回值类型 {执行语句} func test(a int) int { b := a +1 return b }
三、变量
1、变量
1.变量声明的语法
var 变量名 类型 = 表达式 var s string = "我是神" //正常格式 var s string //省略表达的方式,默认为零值 var s = "我是神" //省略类型的方式,由编译器自行判断类型 var s,j,i str //申请多个统一类型的变量,且省略表达式全部为零值。 var b,g,m = true,2.3 ,"four" //申明多个变量,根据表达式编译器自行判断类型 var f,err = os.Open(name) //申请两个变量接收函数的返回值,类型有系统判断。
2.各类型的零值:
数值类型(int):零值为0
布尔类型(bool):零值为false
字符串类型(string):零值为空字符串 ""
接口类型和引用类型(包括slice、map、chan和函数):零值为nil
数组或结构体等聚合类型对应的零值是每个元素或者字段都是对应该类型的零值。
3.零值的意义
a.零值初始化机制可以确保每个声明的变量总是有一个良好定义的值。
b.可以在没有增加额外工作的前提下确保边界条件的合理性为。
c.不至于导致错误或产生不可预知的行为
d.go语言中不存在未初始化的变量。
e.应该让一些聚合类型的零值也具有意义,可以保证无论任何类型的变量总是有一个合理有效的零值状态。
2、简短变量声明
1.简短变量声明的语法
变量名 := 表达式 //上述的变量声明方式都可以用简短变量声明的方式进行声明 s := "我是神" s,j :=os.Open(name)
2.简短变量声明方式注意点
a.只能在函数内部使用,在函数外部使用必须用var声明
b.简短变量声明语句中必须至少要声明一个新的变量
//用简短申明方式声明两个变量 in,err := os.Open(name) //用简短声明方式声明一个变量,另外一个为赋值操作 out ,err := os.Open(name) //没有声明新的变量,不能编译通过 out ,err := os.Open(name)
3、new()函数
1.new()函数的语法
变量名 := new(T) //T为数据类型 p := new(int) fmt.Println(p) fmt.Println(*p) *p = 2 fmt.Println(p) fmt.Println(*p) //0xc00001c060 //0 //0xc00001c060 //2
a.new()函数创建的为变量的内存地址,即指针。数据类型为 *T
b.每次调用new()函数返回的都是新的变量的地址。
2.new函数的注意点
1)new函数这是一个预定义的函数,不是一个关键字。
2)我们可以将new名字重新定义为别的类型
3)new被定义为新的类型的变量名,那么在其作用域内是无法使用new()函数的
func delta (old, new int) int { return new-old } //由于new被定义为int类型的变量,因此在delta函数中是无法使用内置de new()函数的。
4、变量的生命周期
1.什么变量的生命周期
变量的生命周期指的是在程序运行期间变量有效存在的时间间隔。
2.包一级声明的变量的生命周期
和整个程序的运行周期是一直的
3.局部变量的的生命周期
a.从每次创建一个新变量的声明语句开始
b.直到该变量不再被引用为止
v.变量的存储空间可能被回收
d.函数的参数变量和返回值变量都是局部变量,在函数每次被调用是创建。
4.全局变量的保存在堆中,不便于回收和管理,生命周期长。局部变量的保存在栈中,方便回收和管理,生命周期端。使用的技术为“变量逃逸”技术。
四、赋值
1、普通赋值
x =1 //变量名赋值 *p = ture //指针赋值 person.name = “bob” //结构体字段赋值 count[x] = count[x] * scale //数组,slice或map的元素赋值 count[x] *= scale //运算并赋值 v :=1 v ++ //等价于v = v+1 v -- //等价于v= v-1
2、元祖赋值
x,y = y,x //交换x.y位置 a[i] , a[j] = a[j] , a[i] x , y = y , x+y v ,ok = m[key] v ,ok = x.(T) v ,ok = <-ch _,err = io.Copy(dst, src) _为空白标识符,是舍弃掉不需要处理的值。
3、可赋值性
即 “ = ”的左边和右边必须具有相同的数据类型
五、类型
1、类型声明的意义
1.类型声明语句创建了一个新的类型类型名称,和现有的类型具有相同的底成结构。
2.新命名的类型提供了一个方法,用来分隔不同的概念的类型。
3.这样即使底成类型相同也是不兼容的。
//type 类型名字 底成类型 package tempconv import "fmt" type Celsius float64 //摄氏度 type Fahrenheit float64 //华氏度 const ( AbsoluteZeroC Celsius = -273.15 //绝对零度 FreezingC Celsius = 0 //结冰点温度 BoilingC Celsius = 100 //沸水温度 ) func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) } func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) } //!- func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
a.Celsius和Fahrenheit分别对应不同类型的温度单位。
b.他们拥有相同的底成类型float64,但是他们是不同的数据类型。
c.因此他们不能再一起运算,也不能做比较
3、类型转换
a.Celsius(t)和Fahrenheit(t)是类型转化操作,不是说函数调用,而是将值改变为一直对应的类型。
b.对于每一个类型T,都有一个对应的类型转换操作T(x),用于将x转换为T类型。
c.当T为指针类型时,可能需要用小括号包装T,比如(*int)(0)
d.只有两个类型的底成基础结构一致时,才允许转换操作。
e.转换操作只改变类型,不会影响值本身。(但是float转成int时会丢弃小数部分,造成值的改变)
六、包与文件
1、 包的作用
a.go语言中的包和其他语言的库或者模块的概念相似
b.目的是为了支持模块化,封装,单独编译和代码重用
c.一个包的源代码保存在一个或多个以.go为文件后缀名的源文件中
2、包的规则
a.每一个包都对应一个独立的名字空间。(我理解的意思是,每个包的包名都不应相同)
c.通常一个包所在目录路径的后缀是包的导入路径:$GOPATH/src/包名
d.如果导入包但是没有使用到改包,编译时会报错。
3、包的初始化
1.普通的初始化
a.如果包中还有多个.go源文件,它们将按照发给编译器的顺序进行初始化
b.go语言的构建工具首先会将.go文件根据文件名排序,然后依次调用编译器编译
2.复杂的初始化
a.例如某些表格数据初始化应不是一个简单的赋值过程。
b我们可以用init初始化函数来简单初始化工作。
c.每个文件都可以包含多个init初始化函数。