1、结构体的内部变量在别的包调用,要注意大小写
答:在struct中的属性,严格区分首字母大小写,大写为公有属性,别的包可以访问到,小写为私有,别的包访问不到。
例如:
package mainimport( "fmt" "reflect")type People struct{ Age int Name string}func main(){ temp := People{Age:20,Name:"mark"} fmt.Println(temp.Age) fmt.Println(temp.Name) s := reflect.ValueOf(&temp).Elem() s.Field(0).SetInt(30) fmt.Println(s) fmt.Println(temp)}
在golang中,如果结构体的内部变量在别的包调用,会出现类似“implicit assignment of unexported field”的问题。
因为,在golang中,软件结构是以包为单位的,在同一个包内属于内部,不同包之间属于包间。
给外部包用的变量,必须首字母大写,否则就会出现上述问题。
同时,结构体内部的变量,如果不声明为首字母大写的变量,也会出现该问题。
2、使用多层的map,为何报panic ,assignment to entry in nil map
答:多层的map,每一层都要初始化 make()
注意这种map的嵌套的形式,make只初始化了map[string]T部分(T为map[int]int),所以下面的赋值会出现错误:
test := make(map[string]map[int]int)test["go"][0] = 0 // error
正确的做法:
test := make(map[string]map[int]int)test["go"] = make(map[int]int)test["go"][0] = 0
一个常用的做法:
test := make(map[string]map[int]int)if test["go"] = nil { test["go"] = make(map[int]int)}test["go"][0] = 0
3、判断字符串是否包含时,两个比较的参数都要是字符串类型
答:静态语言的类型都是要两种同样的类型才可以比。当不同类型的比较时,要先转换类型。
比如使用
//week是星期几,int类型week := int(time.Unix(time.Now().Unix(),0).Weekday())//week要转换成字符串类型strings.Contains(“1,2,3,4,5,6”, strconv.Itoa(week))
golang中字符串和各种int类型之间的相互转换方式:
string转成int:int, err := strconv.Atoi(string)string转成int64:int64, err := strconv.ParseInt(string, 10, 64)int转成string:string := strconv.Itoa(int)int64转成string:string := strconv.FormatInt(int64,10)
4、Map的增删改,遍历和排序
map类型是常用的一种字典类型,struct结构体的遍历和排序类似map。
增删改:
在Go语言中,Map中的值是不可以修改的。
比如:
package maintype Student struct { Name string Id int}func main() { s := make(map[string]Student) s["chenchao"] = Student{ Name:"chenchao", Id:111, } s["chenchao"].Id = 222}
上面的代码会编译失败,因为在go中 map中的赋值属于值copy,就是在赋值的时候是把Student的完全复制了一份,复制给了map。而在go语言中,是不允许将其修改的。
但是如果map的value为int,是可以修改的,因为修改map中的int属于赋值的操作。
如何在go语言中原地修改map中的value呢? 答案是:传指针!
package mainimport "fmt"type Student struct { Name string Id int}func main() { s := make(map[string]*Student) s["chenchao"] = &Student{ Name:"chenchao", Id:111, } s["chenchao"].Id = 222 fmt.Println(s)}
在结构体比较大的时候,用指针效率会更好,因为不需要值copy
当然,如果map中的value为 *int指针类型,那么在赋值时不可以用&123,因为int为常量,不占内存,没有内存地址
使用 delete() 函数从 map 中删除键值对
其中 map 为要删除的 map 实例,键为要删除的 map 中键值对的键。
scene := make(map[string]int)// 准备map数据scene["route"] = 66scene["brazil"] = 4scene["china"] = 960delete(scene, "brazil")for k, v := range scene { fmt.Println(k, v)}
清空 map 中的所有元素
Go语言中并没有为 map 提供任何清空所有元素的函数、方法,清空 map 的唯一办法就是重新 make 一个新的 map,不用担心垃圾回收的效率,Go语言中的并行垃圾回收效率比写一个清空函数要高效的多。
遍历:
遍历key-value
package mainimport ( "fmt")func main() { var mymap map[string]string mymap = map[string]string{"1a": "Very", "2b": "good", "3c": "day"} for key,value := range mymap { fmt.Println(key,":",value) }}
多层遍历:
for keyA, valA := range mainMapA {for subKeyA, subValA := range valA {fmt.Printf("mapName=%sKey=%sValue=%s", keyA, subKeyA, subValA)}}
map字典按照键排序和按照值排序
字典按键排序
package mainimport ("fmt""sort")func main() {m := map[string]int32{"roy": 18,"kitty": 16,"hugo": 21,"tina": 35,"jason": 23,}lst := []string{}for k, _ := range m {lst = append(lst, k)}sort.Strings(lst) //排序字符串fmt.Println(lst)m1 := map[int]string{19: "roy",41: "kitty",32: "jason",23: "hugo",}lst1 := []int{}for k, _ := range m1 {lst1 = append(lst1, k)}sort.Ints(lst1)//排序int类型fmt.Println(lst1)}
通过结构体实现字典按值排序。
package mainimport ("fmt""sort")func main() {mapInfo := map[string]int32{"roy":18,"kitty":16,"hugo":21,"tina":35,"jason":23,}type peroson struct {Name stringAge int32}var lstPerson []perosonfor k, v := range mapInfo {lstPerson = append(lstPerson, peroson {k, v})}sort.Slice(lstPerson, func(i, j int) bool {return lstPerson[i].Age > lstPerson[j].Age // 降序// return lstPerson[i].Age < lstPerson[j].Age // 升序})fmt.Println(lstPerson)}