GO语言基础学习 | 青训营笔记

103 阅读5分钟

GO语言基础入门

GO语言基础语法

基本变量声明方式

  1. [var 变量名称 变量类型],指定数据类型
var a int 
a = 1

2. [var 变量名称] = xxx, 未指定数据类型, 编译器自行判断类型

  • 下面这个例子是自动判断成为string类型
var a = "string"

3. 变量名称 := 值,直接赋值,不需要声明,下面对比两种表示方式

  • 第一种这种表达方式是正确的:
a := 1 
  • 下面这种表达方式是错误的:编译错误,因为已经生成过了
var a int
a := 1

4. 只声明,不赋值

  • int类型默认为0
  • bool类型默认为false
  • string类型默认为""空字符串
  • 以下类型默认为nil
    • 指针类型
var a *int
    • 数组类型
var a []int
    • 字典类型
var a map[string] int
  • *
var a chan int
    • 函数
var a func(string) int
    • 错误接口,error 是接口
var a error

5. 数组声明方式&初始化

  • var 数组变量名 [元素数量]变量类型
  • var arr [4]int
  • 是不同的数组,因为他们声明时的数组数量不一样
var arr1 [5]int
var arr2 [10]int
arr1 = arr2 //不等同

下面展示几种不同的声明方式,和初始化方式

  • 第一种:声明的时候就初始化,var arr [3]int = [3]int{1,2,3}[3]这个前后都在value_type的前面
  • 第二种:先声明,再赋值,var arr [3]int arr[0] = 1 arr[1] = 2 arr[3] = 3
  • 第三种:跟第一种类似,但是等号后面的[3]不能漏掉var arr = [3]int{1,2,3}
  • 第四种:arr := [3]int{1,2,3}or var arr = [...]int{1,2,3}orvar arr = []int{1,2,3}
  • 第五种:确定index来赋值,arr := [5]int{0:1,4:3}

多变量声明方式

  1. 类型相同多个变量, 非全局变量,和python很像,不需要显示声明类型,自动推断
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3

2. 出现在:=左侧的变量不应该是已经被声明过的,否则会导致编译错误 vname1, vname2, vname3 := v1, v2, v3 3. 因式分解关键字的写法一般用于声明全局变量

var (
    vname1 v_type1
    vname2 v_type2
)

不能重复声明

  • 之前已经被声明过了,这样再次声明不正确a := 20
  • 可以的,这是赋值操作a = 20

引用类型与基本类型

  1. 基本类型: 如果是值被调用,值不会有任何改变 C语言中,函数参数加上&可以改变被调用的值,但是GO语言中不能加,加上会报错
  2. 引用类型: 指针,指向对象存储的地址,输出时必须加上&
  • 下面的例子,add2(n int)是基本类型参数的函数,add2ptr(n *int)是指针类型的函数
add2(n)
fmt.Println(n) // 5
add2ptr(&n)
fmt.Println(n) // 7
}

3. float32和float64之间的区别

  1. 位数不一样
  2. 32占4bytes, 64占8bytes
  3. 数位越高浮点数精度越高

逗号+ok模式

在一个表达式返回2个参数的时候使用,第一个参数是一个值或者nil,第二个参数是true/false或者一个错误error

range

表示方式:range+数组ormap

指针

指针输出时要加上&,不然会报错

func add2ptr(n *int){
    *n += 2
}
func main() {
	add2ptr(&n)
	fmt.Println(n) // 7
}

函数

  1. 函数名前面没有参数是一般的函数
  2. 函数名前面有参数,是结构的方法,GO语言没有类,只有结构
  3. 有返回值的函数要写类型,如下:
func add(a int, b int) int{
    return a + b
}

string的几种方法

  1. 返回bool类型,判断是否有"ll"存在于a
a := "hello"
fmt.Println(strings.Contains(a, "ll")) // true

2. 返回int类型,有几个"l"在a中

fmt.Println(strings.Count(a, "l"))    // 2

3. 返回bool类型,判断a字符串开头是不是"he"

fmt.Println(strings.HasPrefix(a, "he")) //true

4. 返回bool类型,判断a字符串结尾是不是"llo"

fmt.Println(strings.HasSuffix(a, "llo"))//true

5. 返回int类型,判断第一个出现ll的下标在哪里

fmt.Println(strings.Index(a, "ll"))   // 2

6. 返回string类型,将字符串们连接起来,连接符保留

fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo

7. 返回string类型,将a字符串重复一次,共两次

fmt.Println(strings.Repeat(a, 2)) //hellohello

8. 返回string类型,用"E"替代a中的"e",最后的整数表示次数,-1表示不限次数替代

fmt.Println(strings.Replace(a, "e", "E", -1))// hEllo

9. 返回[]string,以"-"为分隔符

fmt.Println(strings.Split("a-b-c", "-")) // [a b c]

10. 返回string类型,全员小写

fmt.Println(strings.ToLower(a))     // hello

11. 返回string类型,全员大写

fmt.Println(strings.ToUpper(a))    // HELLO

12. 返回int类型,字符串长度

fmt.Println(len(a))             // 5

json

定义一个结构体后,给结构体的元素加上一个json后缀json:"age"相当于给他起了一个别名,到时候会显示别名,不会显示原名。如下图所示:

type userInfo struct {
    Name  string
    Age   int `json:"age"`
    Hobby []string
}
打印结果:{"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}  

json中还有序列化json.Marshal()的方法和反序列化json.Unmarshal()的方法;序列化将结构体变成json字符串,反序列化将json字符串反序列化成一个空的变量里面。这样序列化出来的变量,是以每个单词大写开头的,而不是下划线,看看下面的打印结果,对比下,跟上面的有什么区别。

{Name:"wang",Age:18,Hobby:[]string{"Golang","TypeScript"}}

fmt

打印时只有%v会只打印变量的值,如果加上+变成%+v会变得详细一些,如果是%#v,则会更详细,包名变量名都会出现。

fmt.Printf("p=%v\n", p)  // p={1 2}
fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}

设置小数点后面的保留位

fmt.Printf("%.2f\n", f) // 3.14

time

  • time.Localtime.UTC的区别:UTC返回的是零时区的时间,Local返回的是本地时间,比如在北京的话,返回的就是北京时间
  • time.Sub:返回时间间隔,如
t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC) 
t2.Sub(t) //1h5m0s

strconv

  • strconv.ParseInt(string, base, bitSize):将字符转化成为数字,十进制,数字位数
  • strconv.Atoi(string) = strconv.ParseInt(s,10,64)