-
一定要自己动手写,不然使用的时候可能连等号的位置都搞不清楚
-
该语言没有面向对象的概念,什么函数传什么参数返回什么值自己要多练习
-
i++
属于独立语句,不能和其他语句写到一起,自己占一行
-
以下东东需要初始化(开辟空间),包括切片,指针,map
(数组声明后,会填充默认值)
-
函数可返回多个
-
使用:=
声明并赋值,函数外不行
-
const
常量(静态变量)关键字,内部可使用iota
作为计数器赋值
-
iota
只能在常量的表达式中使用
-
每次const
出现都会使iota
归零
-
iota
按行自增,所以同一行的iota
是一样的值
-
可以使用 _
来接收不要的参数,可以用来跳过iota
的值,或者接收函数的返回值时用来占位
-
切片是引用类型,底层数组改变,切片也会变
-
append()
只有两个参数,第一个是被加的切片,第二个是追加的切片,(返回的也是切片),其实就是俩切片相加。
-
append()
第二个参数要加 ...
才是每个值,这是单个添加的特殊写法
-
用于切片的append
函数(追加)需要接收,注意:根据需求,该函数会改变底层数组
testSlice = append(testSlice, 0)
-
指针开辟空间要用new
关键字,其他数组,map
,chan
都需要用make
(make
内部不传入什么实例,没有实例的概念,要传入类型,容量,长度等)
-
但是一般不用new([]int)
来搞指针,为啥要自己建一个空指针呢?空指针会直接报错!应该使用取地址来操作
pointer = &a
-
for k,v := range myArray{}
注意:=
位置
-
copy(切片|数组,切片)
被复制的只能是切片,输出文档上说是切片,可是我实测数组也行,可能是引用类型的原因。
-
copy
输出的也是切片!返回的是长度
func main() {
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中
fmt.Println(slice1)//[1 2 3 4 5]
fmt.Println(slice2)//[1 2 3]
slice1 = []int{1, 2, 3, 4, 5}
slice2 = []int{5, 4, 3}
lenth := copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置
fmt.Println(slice1)//[5 4 3 4 5]
fmt.Println(slice2)//[5 4 3]
fmt.Println(lenth)//3
}
- 集合直接
make
也行,反正都要初始化
- 函数作为接收者,尽量用指针
- 同理,参数也尽量用指针
- 函数调用会复制参数,所以不使用指针不能改变结构体(对象)的值
- 对象/结构体调用函数时,不用管指针还是取地址
*s,&s
,反正go都会自动转换,关键是函数要把接收者写成指针形式。
- 注意
go
对象自动转换不能套环,嵌套无效,案例如下
type Student struct {
age int8
name string
}
type StudentPoint *Student
func (Student) sayHello() { //省略receiver 的参数参数名字
fmt.Println("hello world")
}
func (s Student) showName() {
fmt.Println(s.name)
}
func (s * Student) setName(newName string) {
s.name = newName
}
// Error:接受者(receiver)为指针类型
func (s StudentPoint) showName2(){ // Error:接受者(receiver)为指针类型
fmt.Println(s.name)
}
s := Student{}
s.setName("dq")
//go会自动转为 (&s).setName("dq")
var s2 = &s
s2.showName()
//o会自动转为 (*s2).showName()
- 在结构体中嵌入指针变量,要注意赋值,不然新建一个带有指针的对象,内部指针未赋值,会
panic
,空指针报错。初始化结构体,并不会给一个指针开空间。
type Person struct {
age int8
name string
}
func (s Person) showName() {
fmt.Println(s.name)
}
func (s *Person) setName(newName string) {
s.name = newName
}
type Student1 struct {
Person //Student1包含了Person,那么Student1对应的value和pointer包含Person
}
type Student2 struct {
*Person
}
// 内嵌类型 Persion默认值为 Person{age:0, name:""}
s1 := Student1{}
s1.setName("student1_01") // ok
s1.showName()
// 内嵌类型 *Persion默认值为 nil
s2 := &Student2{}
s2.setName("student1_02") //Error,由于目前内嵌类型的值为nil,会触发报错
s2.showName()
// 给嵌入类型一个复制,就ok了
s3 := &Student2{Person:&Person{age:3, name:"s3"}}
//s3 := &Student2{&Person{age:3, name:"s3"}} 和上一行等价
s3.showName()
-
for i, v := range arr
中i,v
都是复制的,并且只有一个,所以直接取地址,或者希望改变i,v
来改变源数组,都是不行的。直接取地址保存的是复制的v
的地址,其内容就只是循环结束后的内容,每次循环内容都会被改变,指针不变。
func main() {
arr := []int{1, 2, 3}
myMap := make(map[int]*int)
for i, v := range arr {
myMap[i] = &v //错了,v的地址永远不变
}
for _, v := range myMap {
fmt.Println(*v) //输出3,3,3
}
}