[ go 与 golang | 青训营笔记]
这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天, 在学习了go的相关基础知识以后,可以说是初步的了解了go,我在这过程中也记录了一些自己的学习经验以及心得,与大家分享一下。
16. map
声明
map是key-value形式
它的key只能是基本数据类型
// 定义map
var m map[string]string
// 创建空间
m = make(map[string]string, 2) // size可以不写,默认为1
m["name"] = "张三"
m["age"] = "21"
m["addr"] = "湖南长沙"
fmt.Println(m)
简写
m2 := map[string]string{
"name": "张三",
"age": "12",
}
增加
通过map[key] = xxx
查找
通过双赋值检测某个key是否存在
v, ok := m2["name"]
if ok {
// 如果存在,ok就为true
fmt.Printf("v = %v", v)
}else{
fmt.Printf("v不存在")
}
删除
delete(map, key) // 删除单个元素
遍历
map只有len,没有cap
len一个map,得到的就是key的个数
只有for range一种遍历方式
for key, value := range m{
fmt.Printf("key=%v,value=%v\n", key, value)
}
切片中的元素为map类型
var mapSlice = make([]map[string]string, 3)
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
}
fmt.Println("初始化元素:")
// 对切片中的map元素进行初始化
mapSlice[0] = make(map[string]string)
mapSlice[0]["name"] = "小明"
mapSlice[0]["gender"] = "男"
mapSlice[0]["address"] = "长沙"
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
}
map中的值为切片类型
m := make(map[string][]string)
fmt.Println(m)
val := []string{"北京", "上海"}
m["中国"] = val
fmt.Println(m)
m["中国"] = append(m["中国"], "广州", "深圳")
fmt.Println(m)
17. 自定义数据类型
自定义数据类型
假如我想用4位数字表示消息的类型
也用4为数字表示异常的返回值
如果用uint16来表示,就容易搞混
所以就可以自定义一个数据类型
type msgType uint16
var textMes msgType = 1000
// 混用需要类型转换
var u1001 uint16 = 1001
var imageMes msgType = msgType(u1001)
fmt.Printf("textMes=%v, type of is %T\n", textMes, textMes)
fmt.Printf("imageMes =%v, type of is %T\n", imageMes, imageMes )
这个msgType 已经和uint16是属于不同的类型了
如果需要将uint16的变量赋值给msgType 的变量,则需要进行类型转换
类型别名
byte是uint8的别名
rune是int32的别名
type msgType = uint16
var textMes msgType = 1000
// 混用需要类型转换
var u1001 uint16 = 1001
var imageMes msgType = u1001
fmt.Printf("textMes=%v, type of is %T\n", textMes, textMes)
fmt.Printf("imageMes =%v, type of is %T\n", imageMes, imageMes)
类型别名就相当于是将uint16起了一个别的名字
赋值的时候也不用类型转换
18. 结构体
初识结构体
由一组字段构成的一种自定义数据类型
type User struct {
Name string
Id uint32
}
var u1 User = User{
Name: "张三",
}
u1.Id = 10000
结构体字段
结构体可以没有字段
结构体字段通过.访问
继承
package main
import "fmt"
type User struct {
Name string
Age int
password string
}
type Account struct {
User
money float32
Name string
}
func main() {
var ac Account = Account{
money: 21.9,
User: User{
Name: "王五",
Age: 21,
password: "978345",
},
Name: "账户1",
}
fmt.Printf("ac %#v, %T\n", ac, ac)
var u1 = User{
Name: "lisa",
Age: 22,
password: "1233fg",
}
var ac1 Account = Account{
money: 21.9,
User: u1,
}
fmt.Printf("ac1 %#v, %T\n", ac1, ac1)
fmt.Println(ac.money)
fmt.Println(ac.Name)
fmt.Println(ac.User.Name)
fmt.Println(ac.password)
}
方法
package main
import "fmt"
type User struct {
Name string
Age int
password string
}
func (u User) PrintName() string {
u.Name = "张三"
fmt.Println("printName方法: ", u)
fmt.Printf("printName方法内部:%p \n", &u)
return u.Name
}
func main() {
user := User{"王二麻子", 23, "xsdfe23"}
fmt.Printf("main: %p\n", &user)
name := user.PrintName() // 是值传递,
fmt.Println(name, user)
}
结构体指针
type User struct {
Name string
Id uint16
}
var u User = User{
Name: "zhangsan",
}
u.Id = 20
fmt.Println(u)
var u2 *User = &User{
Name: "李四",
}
u2.Id = 21
fmt.Println(u2)
fmt.Printf("u = %+v, type of %T\n", u, u)
fmt.Printf("u2 = %+v, type of %T\n", u2, u2)CopyErrorOK!
继承
type User struct {
Name string
Id uint16
}
type Account struct {
User
password string
}
type Contact struct {
*User
Remark string
}
// 实例化账户
var a1 = Account{
User: User{
Name: "张三",
Id: 1,
},
password: "666",
}
var c1 *Contact = &Contact{
User: &a1.User,
Remark: "王麻子",
}
// 没有重复字段就可以这样简写
c1.Name = "王五" // 等效于 c1.User.Name = "王五"
fmt.Printf("a1 = %+v\n", a1)
结构体标签
type User struct {
Name string `json:"name"`
Id uint16 `json:"id"`
}
这样写好之后,结构体进行json转换的时候,Name就会自动变为name
package main
import (
"encoding/json"
"fmt"
)
type Article struct {
Title string `json:"title"`
Desc string `json:"desc"`
Content string `json:"content"`
Username string `json:"-"` // - 也不参与序列化
LookCount int `json:"look_count"`
Free bool `json:"free"`
password string // 小写字母开头的不会参与序列化
}
func main() {
article := Article{
Title: "golang文档",
Desc: "golang零基础入门,四小时转岗golang开发",
Content: "golang零基础入门,四小时转岗golang开发",
Username: "fengfeng",
LookCount: 1024,
password: "ksd8%38",
Free: true,
}
// 结构体转json
jsonData, err := json.Marshal(article)
if err != nil {
fmt.Println(err)
return
}
jsonStr := string(jsonData)
fmt.Println(jsonStr)
}
方法
和函数没什么区别
只是多了一个形参,是和结构体绑定在一起的
package main
import "fmt"
type User struct {
Name string `json:"name"`
Id uint16 `json:"id"`
}
func (u User) PrintName() string {
return u.Name
}
func main() {
u := User{
Name: "张三",
Id: 1001,
}
fmt.Println(u.PrintName())
}
我们都知道golang的函数都是值传递
所以如果在方法中修改结构体的值
相当于修改的是结构体的副本
type User struct {
Name string `json:"name"`
Id uint16 `json:"id"`
}
func (u User) SetName(name string) {
u.Name = name
fmt.Printf("setName修改之后:u=%+v\n", u)
}
func main() {
u := User{
Name: "张三",
Id: 1001,
}
u.SetName("李四")
fmt.Printf("setName运行完之后,u=%+v\n", u)
}
如果需要修改原结构体,那么需要传递的是结构体的指针
type User struct {
Name string `json:"name"`
Id uint16 `json:"id"`
}
func (u *User) SetName(name string) {
(*u).Name = name
// 也可这样简写
//u.Name = name
fmt.Printf("setName修改之后:u=%+v\n", *u)
}
func main() {
u := User{
Name: "张三",
Id: 1001,
}
u.SetName("李四")
fmt.Printf("setName运行完之后,u=%+v\n", u)
}