模版用iis在自己家电脑上做网站,钓鱼网站源码,宝塔搭建wordpress访问很慢,Wordpress前端用户头像1. Map
map是一种无序的基于key-value的数据结构#xff0c;Go语言中的map是引用类型#xff0c;必须初始化才能使用。
1.1. map定义
Go语言中 map的定义语法如下 map[KeyType]ValueType其中#xff0c; KeyType:表示键的类型。ValueType:表示键对应的值的类型。map类型的…1. Map
map是一种无序的基于key-value的数据结构Go语言中的map是引用类型必须初始化才能使用。
1.1. map定义
Go语言中 map的定义语法如下 map[KeyType]ValueType其中 KeyType:表示键的类型。ValueType:表示键对应的值的类型。map类型的变量默认初始值为nil需要使用make()函数来分配内存。语法为 make(map[KeyType]ValueType, [cap])其中cap表示map的容量该参数虽然不是必须的但是我们应该在初始化map的时候就为其指定一个合适的容量。
1.2. map基本使用
map中的数据都是成对出现的map的基本使用示例代码如下
func main() {scoreMap : make(map[string]int, 8)scoreMap[张三] 90scoreMap[小明] 100fmt.Println(scoreMap)fmt.Println(scoreMap[小明])fmt.Printf(type of a:%T\n, scoreMap)
}输出 map[小明:100 张三:90]100type of a:map[string]intmap也支持在声明的时候填充元素例如
func main() {userInfo : map[string]string{username: pprof.cn,password: 123456,}fmt.Println(userInfo) //
}1.3. 判断某个键是否存在
Go语言中有个判断map中键是否存在的特殊写法格式如下: value, ok : map[key]举个例子
func main() {scoreMap : make(map[string]int)scoreMap[张三] 90scoreMap[小明] 100// 如果key存在ok为true,v为对应的值不存在ok为false,v为值类型的零值v, ok : scoreMap[张三]if ok {fmt.Println(v)} else {fmt.Println(查无此人)}
}1.4. map的遍历
Go语言中使用for range遍历map。
func main() {scoreMap : make(map[string]int)scoreMap[张三] 90scoreMap[小明] 100scoreMap[王五] 60for k, v : range scoreMap {fmt.Println(k, v)}
}但我们只想遍历key的时候可以按下面的写法
func main() {scoreMap : make(map[string]int)scoreMap[张三] 90scoreMap[小明] 100scoreMap[王五] 60for k : range scoreMap {fmt.Println(k)}
}注意 遍历map时的元素顺序与添加键值对的顺序无关。
1.5. 使用delete()函数删除键值对
使用delete()内建函数从map中删除一组键值对delete()函数的格式如下 delete(map, key)其中 map:表示要删除键值对的mapkey:表示要删除的键值对的键示例代码如下
func main(){scoreMap : make(map[string]int)scoreMap[张三] 90scoreMap[小明] 100scoreMap[王五] 60delete(scoreMap, 小明)//将小明:100从map中删除for k,v : range scoreMap{fmt.Println(k, v)}
}1.6. 按照指定顺序遍历map func main() {rand.Seed(time.Now().UnixNano()) //初始化随机数种子var scoreMap make(map[string]int, 200)for i : 0; i 100; i {key : fmt.Sprintf(stu%02d, i) //生成stu开头的字符串value : rand.Intn(100) //生成0~99的随机整数scoreMap[key] value}//取出map中的所有key存入切片keysvar keys make([]string, 0, 200)for key : range scoreMap {keys append(keys, key)}//对切片进行排序sort.Strings(keys)//按照排序后的key遍历mapfor _, key : range keys {fmt.Println(key, scoreMap[key])}
}1.7. 元素为map类型的切片
下面的代码演示了切片中的元素为map类型时的操作
func main() {var mapSlice make([]map[string]string, 3)for index, value : range mapSlice {fmt.Printf(index:%d value:%v\n, index, value)}fmt.Println(after init)// 对切片中的map元素进行初始化mapSlice[0] make(map[string]string, 10)mapSlice[0][name] 王五mapSlice[0][password] 123456mapSlice[0][address] 红旗大街for index, value : range mapSlice {fmt.Printf(index:%d value:%v\n, index, value)}
}1.8. 值为切片类型的map
下面的代码演示了map中值为切片类型的操作
func main() {var sliceMap make(map[string][]string, 3)fmt.Println(sliceMap)fmt.Println(after init)key : 中国value, ok : sliceMap[key]if !ok {value make([]string, 0, 2)}value append(value, 北京, 上海)sliceMap[key] valuefmt.Println(sliceMap)
}
2. 自定义类型与类型别名
2.1. 自定义类型
在Go语言中有一些基本的数据类型如string、整型、浮点型、布尔等数据类型Go语言中可以使用type关键字来定义自定义类型。
自定义类型是定义了一个全新的类型。我们可以基于内置的基本类型定义也可以通过struct定义。例如 //将MyInt定义为int类型type MyInt int通过Type关键字的定义MyInt就是一种新的类型它具有int的特性。
2.2. 类型别名
类型别名是Go1.9版本添加的新功能。
类型别名规定TypeAlias只是Type的别名本质上TypeAlias与Type是同一个类型。就像一个孩子小时候有小名、乳名上学后用学名英语老师又会给他起英文名但这些名字都指的是他本人。 type TypeAlias Type我们之前见过的rune和byte就是类型别名他们的定义如下 type byte uint8type rune int322.3. 类型定义和类型别名的区别
类型别名与类型定义表面上看只有一个等号的差异我们通过下面的这段代码来理解它们之间的区别。
//类型定义
type NewInt int//类型别名
type MyInt intfunc main() {var a NewIntvar b MyIntfmt.Printf(type of a:%T\n, a) //type of a:main.NewIntfmt.Printf(type of b:%T\n, b) //type of b:int
}结果显示a的类型是main.NewInt表示main包下定义的NewInt类型。b的类型是int。MyInt类型只会在代码中存在编译完成时并不会有MyInt类型。
区别总结自定义类型编译后不会改变类型别名编译后将会是真实类型
3. 结构体
Go语言中没有“类”的概念也不支持“类”的继承等面向对象的概念Go语言中通过struct来实现面向对象。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。
3.1. 结构体的定义
使用type和struct关键字来定义结构体具体代码格式如下 type 类型名 struct {字段名 字段类型字段名 字段类型…}其中 1.类型名标识自定义结构体的名称在同一个包内不能重复。2.字段名表示结构体字段名。结构体中的字段名必须唯一。3.字段类型表示结构体字段的具体类型。举个例子我们定义一个Person人结构体代码如下 type person struct {name stringcity stringage int8}同样类型的字段也可以写在一行 type person1 struct {name, city stringage int8}3.2. 结构体实例化
只有当结构体实例化时才会真正地分配内存。也就是必须实例化后才能使用结构体的字段。
结构体本身也是一种类型我们可以像声明内置类型一样使用var关键字声明结构体类型。
3.2.1. 基本实例化 var 结构体实例 结构体类型type person struct {name stringcity stringage int8
}func main() {var p1 person
}初始化操作 p1.name pprof.cnp1.city 北京p1.age 18fmt.Printf(p1%v\n, p1) //p1{pprof.cn 北京 18}fmt.Printf(p1%#v\n, p1) //p1main.person{name:pprof.cn, city:北京, age:18}
我们通过.来访问结构体的字段成员变量,例如p1.name和p1.age等。
3.2.2. 创建指针类型结构体
我们还可以通过使用new关键字对结构体进行实例化得到的是结构体的地址。 格式如下 var p2 new(person)fmt.Printf(%T\n, p2) //*main.personfmt.Printf(p2%#v\n, p2) //p2main.person{name:, city:, age:0}从打印的结果中可以看出p2是一个结构体指针。下面是初始化操作
var p2 new(person)
p2.name 测试
p2.age 18
p2.city 北京
fmt.Printf(p2%#v\n, p2) //p2main.person{name:测试, city:北京, age:18}3.2.3. 取结构体的地址实例化
使用对结构体进行取地址操作相当于对该结构体类型进行了一次new实例化操作。
p3 : person{}
fmt.Printf(%T\n, p3) //*main.person
fmt.Printf(p3%#v\n, p3) //p3main.person{name:, city:, age:0}
初始化操作
p3.name 博客
p3.age 30
p3.city 成都
fmt.Printf(p3%#v\n, p3) //p3main.person{name:博客, city:成都, age:30}
p3.name 博客其实在底层是(*p3).name 博客这是Go语言帮我们实现的语法糖。
3.3 结构体初始化
3.3.1.基本初始化
var p3 person
p3.name 博客
p3.age 30
p3.city 成都
fmt.Printf(p3%#v\n, p3) //p3main.person{name:博客, city:成都, age:30}
3.3.2. 使用键值对初始化
使用键值对对结构体进行初始化时键对应结构体的字段值对应该字段的初始值。
p5 : person{name: pprof.cn,city: 北京,age: 18,
}
fmt.Printf(p5%#v\n, p5) //p5main.person{name:pprof.cn, city:北京, age:18}也可以对结构体指针进行键值对初始化例如
p6 : person{name: pprof.cn,city: 北京,age: 18,
}
fmt.Printf(p6%#v\n, p6) //p6main.person{name:pprof.cn, city:北京, age:18}当某些字段没有初始值的时候该字段可以不写。此时没有指定初始值的字段的值就是该字段类型的零值。
p7 : person{city: 北京,
}
fmt.Printf(p7%#v\n, p7) //p7main.person{name:, city:北京, age:0}3.3.3. 使用值的列表初始化
初始化结构体的时候可以简写也就是初始化的时候不写键直接写值
p8 : person{pprof.cn,北京,18,
}
fmt.Printf(p8%#v\n, p8) //p8main.person{name:pprof.cn, city:北京, age:18}使用这种格式初始化时需要注意 1.必须初始化结构体的所有字段。2.初始值的填充顺序必须与字段在结构体中的声明顺序一致。3.该方式不能和键值初始化方式混用。3.2 匿名结构体
在定义一些临时数据结构等场景下还可以使用匿名结构体。
package mainimport (fmt
)func main() {var user struct{Name string; Age int}user.Name pprof.cnuser.Age 18fmt.Printf(%#v\n, user)
}3.3. 结构体内存布局
type test struct {a int8b int8c int8d int8
}
n : test{1, 2, 3, 4,
}
fmt.Printf(n.a %p\n, n.a)
fmt.Printf(n.b %p\n, n.b)
fmt.Printf(n.c %p\n, n.c)
fmt.Printf(n.d %p\n, n.d)输出 n.a 0xc0000a0060n.b 0xc0000a0061n.c 0xc0000a0062n.d 0xc0000a00633.4. 构造函数
Go语言的结构体没有构造函数我们可以自己实现。 例如下方的代码就实现了一个person的构造函数。 因为struct是值类型如果结构体比较复杂的话值拷贝性能开销会比较大所以该构造函数返回的是结构体指针类型。
func newPerson(name, city string, age int8) *person {return person{name: name,city: city,age: age,}
}调用构造函数
p9 : newPerson(pprof.cn, 测试, 90)
fmt.Printf(%#v\n, p9)3.5.接收者
3.5.1 方法和接收者
Go语言中的方法Method是一种作用于特定类型变量的函数。这种特定类型变量叫做接收者Receiver。接收者的概念就类似于其他语言中的this或者 self。
方法的定义格式如下 func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {函数体}其中 1.接收者变量接收者中的参数变量名在命名时官方建议使用接收者类型名的第一个小写字母而不是self、this之类的命名。例如Person类型的接收者变量应该命名为 pConnector类型的接收者变量应该命名为c等。2.接收者类型接收者类型和参数类似可以是指针类型和非指针类型。3.方法名、参数列表、返回参数具体格式与函数定义相同。举个例子
//Person 结构体
type Person struct {name stringage int8
}//NewPerson 构造函数
func NewPerson(name string, age int8) *Person {return Person{name: name,age: age,}
}//Dream Person做梦的方法
func (p Person) Dream() {fmt.Printf(%s的梦想是学好Go语言\n, p.name)
}func main() {p1 : NewPerson(测试, 25)p1.Dream()
}方法与函数的区别是函数不属于任何类型方法属于特定的类型。
3.5.2. 指针类型的接收者
指针类型的接收者由一个结构体的指针组成由于指针的特性调用方法时修改接收者指针的任意成员变量在方法结束后修改都是有效的。这种方式就十分接近于其他语言中面向对象中的this或者self。 例如我们为Person添加一个SetAge方法来修改实例变量的年龄。 // SetAge 设置p的年龄// 使用指针接收者func (p *Person) SetAge(newAge int8) {p.age newAge}调用该方法
func main() {p1 : NewPerson(测试, 25)fmt.Println(p1.age) // 25p1.SetAge(30)fmt.Println(p1.age) // 30
}3.5.3. 值类型的接收者
当方法作用于值类型接收者时Go语言会在代码运行时将接收者的值复制一份。在值类型接收者的方法中可以获取接收者的成员值但修改操作只是针对副本无法修改接收者变量本身。
// SetAge2 设置p的年龄
// 使用值接收者
func (p Person) SetAge2(newAge int8) {p.age newAge
}func main() {p1 : NewPerson(测试, 25)p1.Dream()fmt.Println(p1.age) // 25p1.SetAge2(30) // (*p1).SetAge2(30)fmt.Println(p1.age) // 25
}3.5.4. 什么时候应该使用指针类型接收者 1.需要修改接收者中的值2.接收者是拷贝代价比较大的大对象3.保证一致性如果有某个方法使用了指针接收者那么其他的方法也应该使用指针接收者。3.6. 任意类型添加方法
在Go语言中接收者的类型可以是任何类型不仅仅是结构体任何类型都可以拥有方法。 举个例子我们基于内置的int类型使用type关键字可以定义新的自定义类型然后为我们的自定义类型添加方法。
//MyInt 将int定义为自定义MyInt类型
type MyInt int//SayHello 为MyInt添加一个SayHello的方法
func (m MyInt) SayHello() {fmt.Println(Hello, 我是一个int。)
}
func main() {var m1 MyIntm1.SayHello() //Hello, 我是一个int。m1 100fmt.Printf(%#v %T\n, m1, m1) //100 main.MyInt
}注意事项 非本地类型不能定义方法也就是说我们不能给别的包的类型定义方法。
3.7. 结构体的匿名字段
结构体允许其成员字段在声明时没有字段名而只有类型这种没有名字的字段就称为匿名字段。
//Person 结构体Person类型
type Person struct {stringint
}func main() {p1 : Person{pprof.cn,18,}fmt.Printf(%#v\n, p1) //main.Person{string:pprof.cn, int:18}fmt.Println(p1.string, p1.int) //pprof.cn 18
}匿名字段默认采用类型名作为字段名结构体要求字段名称必须唯一因此一个结构体中同种类型的匿名字段只能有一个。
3.8. 嵌套结构体
一个结构体中可以嵌套包含另一个结构体或结构体指针。
//Address 地址结构体
type Address struct {Province stringCity string
}//User 用户结构体
type User struct {Name stringGender stringAddress Address
}func main() {user1 : User{Name: pprof,Gender: 女,Address: Address{Province: 黑龙江,City: 哈尔滨,},}fmt.Printf(user1%#v\n, user1)//user1main.User{Name:pprof, Gender:女, Address:main.Address{Province:黑龙江, City:哈尔滨}}
}3.9. 嵌套匿名结构体
//Address 地址结构体
type Address struct {Province stringCity string
}//User 用户结构体
type User struct {Name stringGender stringAddress //匿名结构体
}func main() {var user2 Useruser2.Name pprofuser2.Gender 女user2.Address.Province 黑龙江 //通过匿名结构体.字段名访问user2.City 哈尔滨 //直接访问匿名结构体的字段名fmt.Printf(user2%#v\n, user2) //user2main.User{Name:pprof, Gender:女, Address:main.Address{Province:黑龙江, City:哈尔滨}}
}当访问结构体成员时会先在结构体中查找该字段找不到再去匿名结构体中查找。
3.10. 嵌套结构体的字段名冲突
嵌套结构体内部可能存在相同的字段名。这个时候为了避免歧义需要指定具体的内嵌结构体的字段。
//Address 地址结构体
type Address struct {Province stringCity stringCreateTime string
}//Email 邮箱结构体
type Email struct {Account stringCreateTime string
}//User 用户结构体
type User struct {Name stringGender stringAddressEmail
}func main() {var user3 Useruser3.Name pprofuser3.Gender 女// user3.CreateTime 2019 //ambiguous selector user3.CreateTimeuser3.Address.CreateTime 2000 //指定Address结构体中的CreateTimeuser3.Email.CreateTime 2000 //指定Email结构体中的CreateTime
}3.11. 结构体的“继承”
Go语言中使用结构体也可以实现其他编程语言中面向对象的继承。
//Animal 动物
type Animal struct {name string
}func (a *Animal) move() {fmt.Printf(%s会动\n, a.name)
}//Dog 狗
type Dog struct {Feet int8*Animal //通过嵌套匿名结构体实现继承
}func (d *Dog) wang() {fmt.Printf(%s会汪汪汪~\n, d.name)
}func main() {d1 : Dog{Feet: 4,Animal: Animal{ //注意嵌套的是结构体指针name: 乐乐,},}d1.wang() //乐乐会汪汪汪~d1.move() //乐乐会动
}3.12. 结构体字段的可见性
结构体中字段大写开头表示可公开访问小写表示私有仅在定义当前结构体的包中可访问。
3.13. 结构体与JSON序列化
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON键值对是用来保存JS对象的一种方式键/值对组合中的键名写在前面并用双引号包裹使用冒号:分隔然后紧接着值多个键值之间使用英文,分隔。
//Student 学生
type Student struct {ID intGender stringName string
}//Class 班级
type Class struct {Title stringStudents []*Student
}func main() {c : Class{Title: 101,Students: make([]*Student, 0, 200),}for i : 0; i 10; i {stu : Student{Name: fmt.Sprintf(stu%02d, i),Gender: 男,ID: i,}c.Students append(c.Students, stu)}//JSON序列化结构体--JSON格式的字符串data, err : json.Marshal(c)if err ! nil {fmt.Println(json marshal failed)return}fmt.Printf(json:%s\n, data)//JSON反序列化JSON格式的字符串--结构体str : {Title:101,Students:[{ID:0,Gender:男,Name:stu00},{ID:1,Gender:男,Name:stu01},{ID:2,Gender:男,Name:stu02},{ID:3,Gender:男,Name:stu03},{ID:4,Gender:男,Name:stu04},{ID:5,Gender:男,Name:stu05},{ID:6,Gender:男,Name:stu06},{ID:7,Gender:男,Name:stu07},{ID:8,Gender:男,Name:stu08},{ID:9,Gender:男,Name:stu09}]}c1 : Class{}err json.Unmarshal([]byte(str), c1)if err ! nil {fmt.Println(json unmarshal failed!)return}fmt.Printf(%#v\n, c1)
}3.14. 结构体标签Tag
Tag是结构体的元信息可以在运行的时候通过反射的机制读取出来。
Tag在结构体字段的后方定义由一对反引号包裹起来具体的格式如下 key1:value1 key2:value2结构体标签由一个或多个键值对组成。键与值使用冒号分隔值用双引号括起来。键值对之间使用一个空格分隔。 注意事项 为结构体编写Tag时必须严格遵守键值对的规则。结构体标签的解析代码的容错能力很差一旦格式写错编译和运行时都不会提示任何错误通过反射也无法正确取值。例如不要在key和value之间添加空格。
例如我们为Student结构体的每个字段定义json序列化时使用的Tag
//Student 学生
type Student struct {ID int json:id //通过指定tag实现json序列化该字段时的keyGender string //json序列化是默认使用字段名作为keyname string //私有不能被json包访问
}func main() {s1 : Student{ID: 1,Gender: 女,name: pprof,}data, err : json.Marshal(s1)if err ! nil {fmt.Println(json marshal failed!)return}fmt.Printf(json str:%s\n, data) //json str:{id:1,Gender:女}
}3.15. 删除map类型的结构体
package mainimport fmttype student struct {id intname stringage int
}func main() {ce : make(map[int]student)ce[1] student{1, xiaolizi, 22}ce[2] student{2, wang, 23}fmt.Println(ce)delete(ce, 2)fmt.Println(ce)
}更多https://github.com/lu569368/struct 参考文章
https://www.fansimao.com/945174.html
https://www.fansimao.com/945190.html