type后面接的都是类型
自定义类型和别名
package main import "fmt" type myint int //自定义类型,编译完还保留 type tmpint = int //类型别名,只在代码编写时有效 func main() { var x myint = 10 fmt.Println(x) fmt.Printf("%T\n", x) var y tmpint = 20 fmt.Println(y) fmt.Printf("%T\n", y) //rune就是int32的类型别名 //告诉别人这是一个字符,不是一个数 }
结构体也是用type来定义,类型是package_name.struct_name
package main import "fmt" type student struct { name string age int gender rune hobby []string } func main() { // 声明一个student类 var ydssx student // 通过字段赋值 ydssx.age = 18 ydssx.name = "夜刀神十香" ydssx.gender = '女' ydssx.hobby = []string{"打怪", "摸鱼"} fmt.Println(ydssx) fmt.Printf("%c", ydssx.gender) }
匿名结构体,不用写type和name
package main import "fmt" func main() { // 定义匿名结构体 var x struct { a string b int } x.a = "777" x.b = 777 fmt.Printf("%T %v", x, x) } //struct { a string; b int } {777 777}
结构体本身属于值类型
创建结构体的四种方式
1.像变量一样创建,一一赋值
2.像创建多个变量一样,变量列表复制
3.在2的基础上省略掉键
4.使用new来创建,此时创建的是结构体指针
如果想通过前面的方法来创建结构体指针,只需要使用&取地址就好。
所以结构体基本就可以看作是普通的数据类型,就是赋值方式有三种
其中结构体指针可以直接使用.来进行赋值,这是go中的语法糖
package main import "fmt" type people struct { name int id string } func main() { var a people a.id = "11" a.name = 0 // var a *int = new(int) // *a = 10 // fmt.Printf("%p %v", a, *a) // 结构体指针1 var b *people = new(people) b.id = "777" (*b).name = 1 fmt.Println(b) fmt.Println(*b) fmt.Printf("%T\n", b) fmt.Printf("%p\n", &b) fmt.Printf("%p\n", b) fmt.Printf("%v\n", b) // 结构体指针2 // key-value 初始化 //var c = &people{···} 就是指针了,这种方式较为常用 var c = people{ id: "777", name: 2, } fmt.Println(c) // 使用值列表进行初始化,值的顺序要与结构体定义字段顺序一致 d := people{ 3, "555", } fmt.Println(d) /* {0 11} &{1 777} {1 777} *main.people 0xc000006030 0xc000004090 &{1 777} {2 777} {3 555} */ }
结构体内部字段是连续的,即结构体占用一块连续的内存地址
package main import "fmt" type people struct { name int8 id int8 } func main() { var a people a.id = 1 a.name = 0 fmt.Println(&a.id) //0xc0000140a9 fmt.Println(&a.name) //0xc0000140a8 } 如果数据类型不一样,可能会出现内存对齐
go语言的构造函数约定俗称用new开头
package main import "fmt" type people struct { name int8 id int8 } func newPeople(name int8, id int8) *people { return &people{ name: name, id: id, } } func main() { fmt.Println(*newPeople(1, 2)) } // {1 2}
结构体构造函数返回的是结构体还是结构体指针:
当结构体比较大的时候尽量使用结构体指针,减少程序的内存开销
方法和接收者
方法中的接收者只能写一个
package main import "fmt" // 结构体定义 type dog struct{ name string } // 构造函数 func newDog(name string) dog{ return dog{ name: name, } } // 方法是作用于特定类型的函数 // 接收者表示的是调用该方法的具体类型变量,多用类型名首字母小写表示 func (d dog)bark(){ fmt.Printf("%v www\n",d.name) } func main(){ d1:=newDog("a") d1.bark() }
不能给别的包里面的类型添加方法,只能给自己的包里添加方法
比如要给int添加方法,需要使用type myint int
自定义类型的方式来给myint
添加。
标识符:变量名 函数名 类型名 方法名
Go中如果标识符首字母是大写,就表示对外部可见(外部的,公有的)