GO基础| 青训营笔记

102 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天

这里是本人学习GO基础语法的相关笔记,将供参考,本人有Java后端和c语言经验。

常见语法:

Hello world程序

package main
import "fmt"
func main() {
	fmt.Printf("hello")
}

命令行工具使用

  • go run xxx.go,运行xxx.go文件,后面可以跟着参数
  • go build xxx.go 编译xxx.go文件会生成xxx.exe文件

基础知识点:

  • 标记:键字,标识符,常量,字符串,符号
  • 注释:单行和多行注释
  • 标识符:字符、数字和下划线,首字母不能是数字
  • 字符串+:字符串可以+连接
  • 关键字:一共61个
  • 格式化字符串:%d,%s等

变量使用

基本数据类型

  • bool:只能是true和false
  • 数字类型:整型int、浮点数float和复数
  • 字符串类型:固定长度的字符序列,底层的是一个只读的byte slice
  • 派生类型:指针、数组、结构体、channel、函数、切片、接口、map

变量声明:使用 var和:=和根据值判断

  • var identifier type:多变量var identifier1, identifier2 type
  • v_name := value
  • var v_name = value

GO常量:

运行时不会被修改值,可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

const identifier [type] = value

  • iota,特殊常量,新增一行计数一次,0开始。
func main() {
	var a = "hello"
	var b, c int = 1, 2
	var d = true
	var e float64
	f := float32(e)
	g := a + "foo"
	fmt.Println(a, b, c, d, e, f)
	fmt.Println(g)
	const s = "hello"
	const h = 1
	fmt.Println(s)
	fmt.Println(h, math.Sin(h))
}

常量没有类型,可以通过上下文进行自动判断

运算符:

同c和java类似,不再说明

if、switch、for

if没有()

没有while只有for

switch不用使用break;要达到强制执行下一个case,通过

func main() {
	var a = 1
	switch a {
	case 1:
		fallthrough
	case 10:
		println("hello")
	}
}

数组

声明方式:var variable_name [SIZE] variable_type

  • var balance [10] float32

初始化:var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

访问:var salary float32 = balance[9]

切片Slice

和Java的ArrayList感觉使用上很相似,底层通过数组实现,Slice长度不像普通数组一样固定,能够改变。每次扩容都是扩容为旧容量的两倍,若长度大于等于1024,扩容为原来的1/4。

创建:

  • var slice1 []type = make([]type, len)
  • make([]T, length, capacity) capacity为容量,可选、

相关操作:

  • 切片
  • append,可以往nil的切片添加数据
  • copy
  • len
  • cap

map

声明方式:

  • map_variable := make(map[key_data_type]value_data_type)
  • var map_variable map[key_data_type]value_data_type

注意点:

  • 不可以往nil的map中添加数据
  • map没有对应key的返回值与数据类型匹配,有nil,"",false。所以在判断map中是否包含对应key的时候,不能够把默认返回值作为对比。需要使用返回的error信息作为判断。
    • 例如 if _, ok := x["two"]; !ok { fmt.Println("key two is no entry")}

可用通过map使用空结构体做出一个set来,简单演示一下:m := make(map[string]struct{})

range

range语法,返回两个值,一个是index,一个是value

map进行range,返回k和v,只用一个,返回key,map没有index顺序。

func main() {
	m := make(map[string]int)
	m["k1"] = 1
	m["k2"] = 3
	m["k3"] = 5
	for k, v := range m {
		fmt.Println("key=", k, "value=", v)
	}
}

函数:

func 方法名( 参数列表) 返回值类型{return 返回值列表}

init函数

init函数会在main函数之前触发,这个类似于python的__init__(我记得是)。所以这里能够做到事现注册很多东西的效果。

defer相关:

  • 用于处理panic,其中的recover()不能被函数嵌套。
  • 注意defer函数的作用域,在for循环中的循环变量使用

指针:

和c语言类似。

没有和java一样的this指针,对象都是通过显式进行传递,面向对象的方式不同与java和c++。

结构体:

type person struct {
	name string
	age  int
}

func main() {
	p1 := person{"wth", 21}
	p2 := person{name: "wth", age: 123}
	p3 := person{name: "wht"}
	fmt.Println(p1)
	fmt.Println(p2)
	fmt.Println(p3)
}

结构体方法:

func (变量名 结构体类型) 方法名(参数,参数类型) 返回值{
    
}

错误处理

有异常

func 方法名(参数列表) error {
	return nil
}
func 方法名(参数列表)(返回值列表){} // 返回值列表中包含error

func 方法名(a int, b int) (c int, err error) {
	return a + b, nil
}

nil是空

变量作用域

  • 函数内定义的变量称为局部变量
  • 函数外定义的变量称为全局变量
  • 函数定义中的变量称为形式参数

字符串处理:

字符串格式化:+和#具有很好的详细打印功能功能

%v表示变量的含义,类似于%d,%f,%c等的结合。

fmt.printf("%+v",str);

fmt.printf("%#v",str);

+和#具有很好的详细打印功能功能

JSON处理

结构体,变量名大写就可以。

Marshal,和Unmarshel

数字解析:

strconv.ParseInt("字符串",进制,精度)

strconv.Atoi("字符串")//字符串到数字。

总结

go语言语法比较简单,上手比较容易

  • defer关键字比较特别。
  • switch比较特别
  • panic处理,需要在defer中直接使用recover,嵌套使用会失败。