1、结构体的内部变量在别的包调用,要注意大小写
答:在struct中的属性,严格区分首字母大小写,大写为公有属性,别的包可以访问到,小写为私有,别的包访问不到。
例如:
package main
import(
"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 main
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
}
上面的代码会编译失败,因为在go中 map中的赋值属于值copy,就是在赋值的时候是把Student的完全复制了一份,复制给了map。而在go语言中,是不允许将其修改的。
但是如果map的value为int,是可以修改的,因为修改map中的int属于赋值的操作。
如何在go语言中原地修改map中的value呢? 答案是:传指针!
package main
import "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"] = 66
scene["brazil"] = 4
scene["china"] = 960
delete(scene, "brazil")
for k, v := range scene {
fmt.Println(k, v)
}
清空 map 中的所有元素
Go语言中并没有为 map 提供任何清空所有元素的函数、方法,清空 map 的唯一办法就是重新 make 一个新的 map,不用担心垃圾回收的效率,Go语言中的并行垃圾回收效率比写一个清空函数要高效的多。
遍历:
遍历key-value
package main
import (
"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\n", keyA, subKeyA, subValA)
}
}
map字典按照键排序和按照值排序
字典按键排序
package main
import (
"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 main
import (
"fmt"
"sort"
)
func main() {
mapInfo := map[string]int32{
"roy":18,
"kitty":16,
"hugo":21,
"tina":35,
"jason":23,
}
type peroson struct {
Name string
Age int32
}
var lstPerson []peroson
for 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)
}