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中如果标识符首字母是大写,就表示对外部可见(外部的,公有的)