golang基础

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)
}

版权

本作品采用 CC BY-NC-ND 4.0 授权,转载必须注明作者和本文链接。

上一篇:golang的一些总结
下一篇:Helm包管理工具