map
map是一个key-value的数据结构,又称为字段或关联数组
Golang自带的map是哈希表
声明
import "fmt"func main() { var a map[int]int fmt.Println(a)}
slice,map和func不能作为键值
声明map是不会分配内存的,初始化需要用make
import "fmt"func main() { var a map[int]int a = make(map[int]int, 3)//可以存放三个键值对 fmt.Println(a)}
Go的map的键值是没有顺序的
自动增长
func main() { a := make(map[int]int) a[1] = 2 a[2] = 1 fmt.Println(a)}
直接初始化
func main() { a := map[int]int{ 1: 1, 2: 2,//这里也要, } fmt.Println(a)}
增加和更新
直接给键值赋值即可
删除
delete(map, 1)//删除map键值为1的对,如果不存在不会操作
如果要完全清空
遍历key来删除,或者让map赋值一个新的map,给GC回收
查询
val, flag := mp[1] //flag是bool,找到是true,没找到是false,val是对应值
遍历(for-range)
func main() { a := map[int]int{ 1: 1, 2: 2, } for k, v := range a { fmt.Println(k, v) } fmt.Println(a)}
map切片
同样slice的用法,注意map也要make就行,相当于在底层维护一个map类型的数组
关于哈希表遍历的一点看法
大概是这样的,在底层有一个迭代器链表,或者,有一个指针数组,每次存放一个指针,迭代器依次访问这些指针,但是在添加元素的时候, 会rehash,导致顺序变化。所以Go的设计者把他设置成无序,每次都打乱这个数组,防止程序员误用哈希map
对map的key排序
将键值追加到切片内,然后对切片排序
import ( "fmt" "sort")func main() { mp := make(map[int]int, 10) mp[1] = 2 mp[3] = 1 mp[2] = 5 mp[5] = 6 var keys []int //切片 for key, _ := range mp { keys = append(keys, key) } sort.Ints(keys) fmt.Println(keys)}
map是引用类型
结构体与OOP
声明、初始化、序列化
go语言是用struct来面向对象的
声明
type Node struct { X int Y int}func main() { var a Node//空间自动分配 fmt.Println(a)}//输出{0 0}
赋值
func main() { var a Node a.X = 1 a.Y = 2 fmt.Println(a)}//输出{1 2}
初始化
//方法一a := Node{1, 2}//方法二ptr *Node = new(Node)(*ptr).X = 1(*ptr).Y = 2//--------func main() { var ptr *Node = new(Node) (*ptr).X = 1 (*ptr).Y = 2 fmt.Println(*ptr)}//---底层自动识别,这样也可以func main() { var ptr *Node = new(Node) ptr.X = 1 ptr.Y = 2 fmt.Println(*ptr)}//方法三var node *Node = &Node{}
结构体的所有字段在内存中是连续的
两个结构体的字段类型完全相同的话可以强制类型转换
用type struct1 struct2给struct2取别名,相当于定义了一个新的类型,两者之间可以强制类型转换,但是不能直接赋值
struct的每个字段上可以写上一个tag,该tag可以通过反射机制获取,常见于序列化和反序列化
复习一个点,Go没有public和private,所以用首字母大写和小写来确定是公共的还是私有的
序列化:对象转json字符串
反序列化:json字符串转对象
动手
import ( "encoding/json" "fmt")type Node struct { Name string Password string}func main() { a := Node{ "aaaaaa", "123456", } str, _ := json.Marshal(a) fmt.Println(a) fmt.Println(string(str))}//输出//{aaaaaa 123456}//{"Name":"aaaaaa","Password":"123456"}
但是这种大写的变量很多客户端不习惯,所以使用tag,如果使用小写,就无法被结构体外部函数使用,无法序列化
import ( "encoding/json" "fmt")type Node struct { Name string `json:"name"` Password string `json:"password"`}func main() { a := Node{ "aaaaaa", "123456", } str, _ := json.Marshal(a) fmt.Println(a) fmt.Println(string(str))}//输出//{aaaaaa 123456}//{"name":"aaaaaa","password":"123456"}
方法
方法是作用在指定类型上的函数
func (a Node) ok() { fmt.Println("ok")}//这个函数绑定给了Node//调用var a Node p.ok()
动手
import ( "fmt")type Node struct { Name string `json:"name"` Password string `json:"password"`}func (a Node) ok() { fmt.Println(a.Name)}func main() { a := Node{ "aaaaaa", "123456", } a.ok()}//输出了Node的名字
这个方法只能用指定类型来调用,不能直接调用
如果想要修改原来的参数,我们使用结构体指针,并且这更常用,不用深拷贝,速度更快
type Node struct { Name string `json:"name"` Password string `json:"password"`}func (a *Node) ok() { a.Name = "bbbb"}func main() { a := Node{ "aaaaaa", "123456", } a.ok()//编译器底层自动识别变为&a fmt.Println(a)}
可以通过实现String方法,可以自定义格式化输出文章来源:https://www.toymoban.com/news/detail-670400.html
工厂模式
类似于构造函数,在结构体所在包下写相应构造的函数,返回结构体指针,这样就可以在结构体私有的情况下,在其他包调用这个函数直接返回结构体对象文章来源地址https://www.toymoban.com/news/detail-670400.html
到了这里,关于Golang中map的使用详解及注意事项的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!