string不可变,当使用range遍历时,自动转换为[]rune
s := "hello 中国"
for c, v := range s {
fmt.Printf("%d %c\n", c, v)
}
byte可变,按照utf-8输出
- byte中的汉字被解码为3个字节
- rune可变,按照unicode输出
- rune=int32 四个字节,byte=int8 1个字节
s := "hello 中国"
a := []byte(s)
for c, v := range a {
fmt.Printf("%d %d\n", c, v)
}
json与map之间的相互转换
m := make(map[string]interface{}, 4)
m["company"] = "byte"
m["subjects"] = []string{"GO", "C++", "Java"}
m["ok"] = true
m["price"] = 666.666
//编码成json
//result, err := json.Marshal(m)
result, err := json.MarshalIndent(m, "", " ")
if err != nil {
fmt.Printf("error: %s", err)
return
}
fmt.Printf("result = %v", string(result))
json与结构体之间的转换
json转结构体
package main
import (
"encoding/json"
"fmt"
)
// 变量名要大写
type IT struct {
Company string `json:"company"`
Subject []string `json:"subjects"`
Isok bool `json:"-"` //不输出
Price float64 `json:",string"`
}
func main() {
//定义一个结构体变量 同时初始化
s := IT{"BJY", []string{"GO", "PHP", "Python", "Java"}, true, 666.66}
//buf, err := json.Marshal(s)
buf, err := json.MarshalIndent(s, "", " ")
if err != nil {
fmt.Printf("error %s", err)
}
fmt.Printf("%+v", string(buf))
}
结构体转json
package main
import (
"encoding/json"
"fmt"
)
type IT struct {
Company string
Subject []string
Price float64
}
func main() {
result := `{
"Company": "bytedance",
"Subject": ["GO","C++","Python","Java"],
"Price": 666.66
}`
var it IT
err := json.Unmarshal([]byte(result), &it)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%#v\n", it)
}
golang中的自定义排序
golang内置了一些基础数据类型的排序,如int,string,float等,其他类型的结构体需要自己实现less, swap,len三个函数。
package main
import (
"fmt"
"sort"
)
func main() {
// int排序
ints := []int{1, 8, 4, 5}
sort.Ints(ints)
fmt.Println(ints)
// string排序
names := []string{"hello", "world", "yao", "jun"}
sort.Strings(names)
fmt.Println(names)
}
自定义排序
package main
import (
"fmt"
"sort"
)
type Student struct {
name string
age int
}
type stuSlice []Student
func (s stuSlice) Len() int {
return len(s)
}
func (s stuSlice) Less(i, j int) bool {
return s[i].age < s[j].age
}
func (s stuSlice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func main() {
students := []Student{{"mike", 16}, {"jane", 22}, {"Ben", 19}}
sort.Sort(stuSlice(students))
for k, v := range students {
fmt.Println(k, v)
}
}
golang中的单元测试
- t *testing.T 普通测试函数
- b *testing.B benchMark测试
普通测试函数
Go test不保证多个test按照顺序执行,但是我们通常会要求按照顺序执行。 使用t.Run来执行subtests可以做到控制test执行的顺序
package main
import (
"fmt"
"testing"
)
func TestF(t *testing.T) {
t.Run("a1", func(t *testing.T) { fmt.Println("a1") })
t.Run("a2", func(t *testing.T) { fmt.Println("a2") })
t.Run("a3", func(t *testing.T) { fmt.Println("a3") })
}
使用TestMain作为初始化test,并且使用m.Run()来调用其他tests可以完成一些需要初始化操作的testing,比如数据库连接,文件打开,rest服务登录等。如果没有在TestMain中调用m.Run()则除了TestMain以外的其他tests都不会被执行。
func TestMain(m *testing.M){
fmt.Println("test main first")
m.Run()
}
二、benchmark函数一般以BenchMark开头
benchmark函数的case一般会跑b.N次,而且每次执行都会如此 在执行过程中会根据实际case的执行时间是否稳定会增加b.N的次数以达到稳态
编码
- 一个英文字符对应一个byte,一个中文字符对应三个byte。
- 一个rune对应一个UTF-8字符,所以一个中文字符对应一个rune。%c输出对应的字符和汉字。 rune相当于go的char。 byte=uint8 rune=uint32
读一行
bf := bufio.NewReader(os.Stdin)
ss, errs := bf.ReadString('\n')
lst := string.Field(ss) //按照空格切分字符串
数组初始化
cities := [...]string{"北京", "上海","深圳"}
cities := []string{"上海", "成都"}
for index,value := range cities{
fmt.Println(index, value)
}
golang中切片的坑
package main
import "fmt"
func modifySlice(s []string) { //切片新增无效
s[0] = "modify 123"
s = append(s, "456")
}
func main() {
s := []string{"123"}
modifySlice(s)
fmt.Println(s) //返回结果 [modify 123] 新增的数据没有生效
s = modifySliceNew(s)
fmt.Printf("%v", s) //必须重新接收返回值 此时生效 因为修改的指针返回了
}
// 原因是传入的参数是指针的拷贝 但是新增数据是修改的指针
func modifySliceNew(s []string)[]string{ //切片新增生效
s[0] = "modify 123"
s = append(s, "456")
return s
}
golang中删除切片中某个元素
- 方法1: 删除某个元素后,剩余的元素往前移动
- 方法2: 重新开一个切片,把满足条件的往新切片中放入
- 方法3: 索引累计,如果是删除的元素索引就不加1,最后根据累计的索引进行切片
package main
import (
"fmt"
)
func main() {
//创建一个slice
sliceU := []int{1, 0, 1, 1, 0, 1, 0, 1, 1}
// 要求:把切片中所有的0删除掉
//slice的删除方式1
//删除剩余的元素往前移动
for i, v := range sliceU {
if v == 0 {
sliceU = append(sliceU[:i], sliceU[i+1:]...)
}
}
fmt.Println(sliceU)
//slice的删除方式2
//重新开一个数组,把满足条件的往新数组中写入
var newSliceU []int
for _, v := range sliceU {
if v != 0 {
newSliceU = append(newSliceU, v)
}
}
fmt.Println(newSliceU)
// slice的删除方式3
// 索引累计 最后切片
index := 0
for _, v := range sliceU {
if v != 0 {
sliceU[index] = v
index++
}
}
fmt.Println(newSliceU[:index])
}
数组传参
package main
import "fmt"
func f(arr [10]int){ //不仅是数组还必须长度一致
arr[1] = 100
fmt.Println(arr)
}
func main(){
/*
数组:类型和长度确定。
值类型:传递参数时,进行值拷贝。
*/
var arr [10]int
arr[1] = 2
arr[2] = 3
f(arr)
fmt.Println(arr)
arr2 := arr
arr2[1] = 100 //拷贝以后改变 没影响
fmt.Println(arr2)
fmt.Println(arr)
}