学习这件事不在乎有没有人教你,最重要的是在于你自己有没有觉悟和恒心。————法布尔

慢生活

Golang 语言学习零碎记录(未整理)

  • 2020-09-02 21:28
简介 :学习学习golang语言,体会体会编译的快乐,简洁随性的舒畅

Golang学习记录

学习问题记录

  1. 只有字符串类型才可以拼接,如果非string类型进行拼接操作,底层不会转换类型。会抛出异常。
  2. 函数内部可以使用 := 或var 进行变量声明 。函数外使用var关键字声明变量,函数外部声明得变量为全局变量。函数内部声明定义得变量,必须使用否则会异常。全局变量可不使用。
  3. 对于包,除了main包可以有main函数外,其他包不可有main函数,并且变量,方法以大写字母开头得为public否则为private包含下划线等。公共得可以对外使用。其他包引入可以直接调用。私有无法调用在外部被引入时。
  4. 算术运算强制数据类型为数据浮点。或int类型。
  5. map需要使用make初始化操作才可以赋值,否则nil默认无法赋值。
  6. Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。
  7. Go语言不支持隐士转换类型,必须声明转换 int32(32)。
  8. 采用utf-8 编码

指针

  • 传值方式。*int。 一个int类型的指针类型
  • ¶m 返回变量param的指针

字符

  • byte (实际上是 uint8 的别名),代表UTF-8字符串的单个字节的值
  • rune 代表单个Unicode字符

变量声明

  • Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。函数内部可以使用 := 或var 进行变量声明变量。定义的变量必须要使用,但是全局变量是允许声明但不使用的。注意 := 左侧如果没有声明新的变量会报编译错误。:= 有定义变量作用。赋值不可用:=
  • 例如:
  • var intVal int
  • intVal :=1 // 这时候会产生编译错误
  • intVal,intVal1 := 1,2 // 此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句
  • #变量声明使用 var 关键字。
  • var identifier(变量名称) type(数据类型)
  • #连贯多个变量声明:
  • var identifier1, identifier2 type = v1 , v2
  • 同一类型的多个变量可以声明在同一行
  • var ( //这种一般声明为全局变量。并且类型是必须指定
  • a int
  • b string
  • )
  • #不声明数据类型系统自动判断类型
  • var identifier = 123
  • #如果不赋值默认值的话:
  • 数值类型(包括complex64/128) 默认为 0
  • 布尔类型默认为false
  • 字符串为默认 ""(空字符串)
  • 以下几种类型默认为 nil:
  • var a *int # 指针引用
  • var a []int # int类型数组
  • var a map[string] int # 字典类型 key为string类型值为int类型
  • var a chan int
  • var a func(string) int
  • var a error // error 是接口
  • # 常量关键字 const 定义方式同上变量定义,常量定义必须赋值
  • const (
  • a = 1
  • b
  • c
  • d
  • )
  • // 定义常量时如果不给默认值,默认使用挨着自己得上行的表达式得值。
  • 常量实现枚举类型 特殊 iota常量用法
  • const (
  • a = iota
  • b
  • c
  • )
  • // 输出 a = 0 b = 1 c = 2
  • # const 跟 iota 案例,每当 iota 在新的一行被使用时,它的值都会自动加 1, iota 理解为行的索引?
  • const (
  • a = iota //0
  • b //1 累加
  • c //2
  • d = "ha" //独立值,iota += 1 = 3 独立值后下面未赋值使用上面ha
  • e //"ha" iota += 1 = 4
  • f = 100 //iota +=1 = 5
  • g //100 iota +=1 = 6
  • h = iota //7,恢复计数 = 7
  • i //8
  • )
  • fmt.Println(a,b,c,d,e,f,g,h,i)

golang 面向对象编程

  • golang语言仅支持封装,不支持继承跟多太。
  • golang没有class声明。只有struct
  • 结构体定义, 结构体内,小写开头字母也是类似private外包不可访问
  • type blog struct {
  • title string
  • id uint
  • }
  • golang struct 中字段tag属性
  • type blog1 struct {
  • title string `json:"name"`
  • id uint
  • }
  • 声明变量结构
  • // 默认值方式
  • asdf := blog{"xxxx-title",123,"afsdfasfasdfasdf"}
  • asdf := blog{title:"xxxx-title",id:123,summary:"afsdfasfasdfasdf"}
  • // 声明后赋值方式
  • var testStruct blog
  • testStruct.title = "xxxx"
  • testStruct.id = 123
  • 其他方式
  • rect1 := new(Rect) // new 返回指针
  • rect2 := &Rect{}
  • rect3 := &Rect{0, 0, 100, 200}
  • rect4 := &Rect{width: 100, height: 200}
  • // 隐式声明匿名字段 (可以玩继承属性?)
  • type book struct{
  • blog // blog结构体类型
  • name string
  • }
  • var xxx book
  • xxx = book{blog{1,"xxx","xxx"},"book name"}
  • 访问: xxx.title xxx.id xxx.name
  • 修改: xxx.title = "sfasdf"
  • 如果有相同得key字段, 需要加上执行类型结构方式 xxx.blog.title
  • -----------------------
  • // 隐式匿名方法得继承,看下面?
  • type Rect struct{ //定义矩形类
  • x,y float64 //类型只包含属性,并没有方法
  • width,height float64
  • }
  • func (r *Rect) Area() float64{ //为Rect类型绑定Area的方法,*Rect为指针引用可以修改传入参数的值
  • return r.width*r.height //方法归属于类型,不归属于具体的对象,声明该类型的对象即可调用该类型的方法
  • }
  • 上面Area() 方法,如果结构定定义了,其他结构体使用该rect结构体未匿名字段,则同样继承了该方法。这就是方法得继承。
  • 在Go语言中,你可以给任意类型(包括内置基本类型,但不包括指针类型)添加相应的方法:
  • type Integer int
  • func (a Integer) Less(b Integer) bool {
  • return a < b
  • }
  • var a Integer = 123
  • if(a.Less(3)) {
  • }
  • 要访问成员变量,可以有两种方式:
  • 1.通过 struct 变量.成员 变量来访问。
  • 2.通过 struct 指针.成员 变量来访问。
  • test := book{title:"xv"}
  • test.title
  • func changeBook(book *Books) { // 指针访问变量
  • book.title = "book1_change"
  • }

Golang Map集合

  • Map 是一种无序的键值对的集合,Map 是无序的,我们无法决定它的返回顺序, 使用range遍历无法保证顺序输出,无法切片
  • /* 声明变量,默认 map 是 nil */
  • var map_variable map[key_data_type]value_data_type -------> var map_test map[int]string key是整数类型 val是字符串类型
  • 如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对无法动态赋值,会报panic: assignment to entry in nil map,如下代码操作就会异常
  • var map_test map[int]string
  • map_test[0] = "string value"
  • fmt.Println(map_test)
  • // 上面报错需要使用make初始化map 如下
  • var map_test map[int]string
  • map_test = make(map[int]string)
  • map_test[0] = "string value"
  • fmt.Println(map_test)
  • /* 使用 make 函数 */
  • map_variable := make(map[key_data_type]value_data_type)

Golang 包的管理

  • 1. 每个包对应一个文件目录,这个文件目录名一般跟包名一致,但并非强制要求。 如下一个项目目录的结构:
  • |-- bin
  • |-- pkg
  • |-- src
  • |-- main
  • |------- main.go package main main 包
  • |-- utils
  • |------- utils.go package utils utils 包
  • |------- utils2.go package utils utils 包 一个目录下可以有很多go源代码但是package必须是同一个utils包,不同文件也不能有相同函数名,变量名等,如果这样的话,外部调用编译无法区分。抛出异常,并且包名不能为main,如果供外包调用的话。
  • 2. 其他包要使用utils包的话,需要将其引入进来,类似其他语言的require,但是golang的引入关键词是 import 例如:
  • import (
  • t "time" 可以起个别名
  • "utils" 引入路径是从 $GOPATH路径下的src目录开始找,所以直接引入utils目录相当于 $GOPATH/src/utils
  • . "fmt" 这个点操作的含义就是这个包导入之后在你调用这个包的函数时,你可以省略前缀的包名,也就是前面你调用的fmt.Println("hello world")可以省略的写成 Println("hello world")
  • _ "github.com/ziutek/mymysql/godrv" _(下划线) 操作其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的 init函数。
  • )
  • 包里面的如果需要让其他外包调用首字母要大写,否则小写。类似其他语言的 publicprivate
  • 3. 如果需要将文件编译成一个可执行的二进制文件,则包名需是main。 如果编译整个项目,有且只能有一个main入口文件。编译整个项目时,需要切换目录到 $GOPATH 目录下,编译文件 main.go 如上目录只要执行 如下命令就可以了:
  • go build -o bin/main main
  • 参数解释:
  • -o 类似output意思跟编译c代码一样,告诉编译器将二进制文件存放到指定位置,指令是将二进制放在bin目录下,没有自动生成。
  • main。上面目录结构编译到main包所在目录,不需要带src,编译器自动在$GOPATH的src路径下发现。
  • 4. 相同目录下得同一个包,不需要import引入,可以直接调用

Golang 函数中的defer

  • defer(延迟执行) 作用是函数执行完毕后才执行的操作:
  • func test() int {
  • defer fmt.Println("test 函数执行完成了, 执行defer了,作用及时释放不必要的资源,如数据库连接,锁等")
  • fmt.Println("hello world")
  • return 1
  • }
  • 程序执行到defer不会立即执行。会执行下面,如果多个defer声明,哪个先声明,哪个后执行。先入后出

Golang 接口 interface

  • Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
  • interface 是一组method 的组合,我们通过interface 来定义对象的一组行为。
  • 使用接口方式实现面向对象的多太。
  • type demo interface {
  • testa() int
  • }
  • type ooo struct{
  • }
  • func (o *ooo) testa() int {
  • return 1
  • }
  • var p demo
  • p = new(ooo)
  • p.testa()

Golang 并发编程

Top