《Go语言圣经》笔记

文件组成

特点:

  • Go是一门编译型语言,Go语言的工具链将源代码及其依赖转换成计算机的机器指令(译注:静态编译)
  • Go语言原生支持Unicode,它可以处理全世界任何语言的文本

组成:

  • 通过包(package)的方式组织代码import
  • 组成程序的声明种类
    • 常量 - const
    • 变量 - var
    • 函数 - func
    • 类型 - type
  • 初始化函数init
  • 可执行程序入口函数main

例子:

// 声明一个可执行程序(main 比较特殊)
package main

// 通过包组织代码运行和调用
import "fmt"

// 常量 & 变量
const LEVEL = "V5"

var name string

// 初始化
func init() {
   
	name = "中国"
}

// 程序执行入口
func main() {
   
	fmt.Println(name, LEVEL, ":Hello word!")
}

基础语法

命名

一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线

区分大小写

开头字母的大小写决定了名字在包外的可见性。大写表示外部可见( 中文汉字现在默认为小写,未来不一定),否则为包内可见

尽量使用驼峰式命名方式,避免缩写单词大小写混用(setByCas => setByCAS

保留关键字如下,保留关键字不允许使用到命名中:

break      default       func     interface   select
case       defer         go       map         struct
chan       else          goto     package     switch
const      fallthrough   if       range       type
continue   for           import   return      var

预定义名称(可以使用作为命名):

内建常量: true false iota nil

内建类型: int int8 int16 int32 int64
         uint uint8 uint16 uint32 uint64 uintptr
         float32 float64 complex128 complex64
         bool string 
         byte  // 自动类型转换, 默认:int8 中文:int32,可用ASCII码 10进制、16进制、单引号 表示
		 rune  // int32 的别名,代表一个Unicode码
		 error

内建函数: make len cap new append copy close delete
         complex real imag
         panic recover

变量

语法
var 变量名[ [*]类型] =

值和类型可以省略其中一个:

  • 省略类型: 根据初始化表达式来推导变量的类型信息。
  • 省略值 : 用零值初始化该变量。
短变量声明
  • 声明和初始化局部变量
    • 允许部分变量已经声明;执行部分初始化,部分声明+初始化
    • 不允许全部变量都声明;全部声明的变量不应该用短变量声明;应该用元组赋值-多重赋值
  • 类型根据表达式来自动推导
零值
数值类型   `0`
布尔类型   `false`
字符串     `""`(空字符串)

接口或引用类型(包括slice、指针、mapchan和函数)  nil

数组或结构体等聚合类型  每个元素或字段都是对应该类型的零值
指针

一个指针的值是另一个变量的地址。一个指针对应变量在内存中的存储位置。

p := &s
fmt.Printf("类型:%T \n", p)
fmt.Printf("指针变量地址:%p 指针变量内容:%v 调用时的地址:%p \n", &p, p, &*p)
fmt.Printf("底层数据地址:%p \n", &s)

// 类型:*string 
// 指针地址:0xc000006030 指针内容:0xc00003a1f0 调用时的地址:0xc00003a1f0 
// 底层数据地址:0xc00003a1f0 
生命周期
  • 全局变量:位于包一级的变量。它们的生命周期和整个程序的运行周期是一致的。
  • 局部变量:位于函数内的变量。每次从创建一个新变量的声明语句开始,直到该变量不再被引用为止,然后变量的存储空间可能被回收

变量逃逸:

针对局部变量的回收特性, 如果将指向短生命周期对象的指针保存到具有长生命周期的对象中,特别是保存到全局变量时,会阻止对短生命周期对象的垃圾回收(从而可能影响程序的性能) 。

说人话:当全局变量指针指向局部变量的内存地址(global = &part),就会导致内存不回收。

赋值

  • 类型必须完全匹配,在赋值语句左边的变量和右边最终的求到的值必须有相同的数据类型
  • nil可以赋值给任何指针或引用类型的变量
  • 元组赋值允许同时更新多个变量的值( 多重赋值 可以用于交换两个变量)
    • 先右后左
    • 将右边各个表达式的值赋值给左边对应位置的各个变量

类型

type 类型名字 底层类型

包的惯例
  1. 必须在头部声明自己的包名
  2. 每个包全部都在一个单独的目录里。一个目录不存在多个包、一个包不会存在多个目录。
  3. 包名应保持小写、简洁
main包
  1. 编译程序会将这种名字的包编译为二进制可执行文件。 可执行程序必须有一个main的包
  2. 必须存在一个main()函数
导入

导入使用关键字 import;导入的方式分为以下三种:

  • 远程导入import "github.com/spf13/viper"
  • 命名导入import myviper "mylib/viper"。一般用于解决冲突或者别名
  • 空白标识符导入import _ "db/driver/mysql"。一般用于初始化代码才会如此
init函数
  1. 每个包可以包含多个init()函数。
    1. 支持单个文件多个
    2. 支持多个文件多个
  2. main()之前运行

PS - 部分场景:在 init()中初始化向某个插件注册功能。可执行程序处引用包含init()的文件、包

执行顺序
  1. import subPkg. 引入包
  2. const. 常量定义
  3. var. 变量定义
  4. subPkg.init(). 引入包执行 init
    1. 以导入声明的顺序初始化
  5. init(). 优先包含 main函数的 init(), 然后其他 init()
  6. main(). 当前main
常见工具
  • go env.查看环境变量
  • go list.查看依赖包
  • go build.编译包和依赖项
    • go build -race竞争检测器来编译并执行
  • go run.编译并运行Go程序
  • go vet.代码错误检查
  • go fmt.代码格式化
  • go get.下载 && 安装软件包和依赖(远程)
  • go install.编译 && 安装软件包和依赖项(本地)

数据类型

Go语言将数据类型分为四类:基础类型复合类型引用类型接口类型

  • 基础类型:数字、字符串和布尔型。
  • 复合类型:数组、结构体 是通过组合简单类型,来表达更加复杂的数据结构。
  • 引用类型:指针、切片、映射、函数、通道
  • 接口类型:接口

基础类型

运算符

优先级排序:

*      /      %      <<       >>     &       &^
+      -      |      ^
==     !=     <      <=       >      >=
&&
||

%(取模):仅用于整数间的运算。取模结果符号与被取模数值一致

-5%3	// -2
-5%-3	// -2

/(除法):用于整数时会采用去尾法

5/2		// 2
5.0/2.0	// 2.5

算数运算时,高位溢出直接丢弃无关符号

var u uint8 = 255
fmt.Println(u, u+1, u*u) // "255 0 1"

类型转换时:

  • 大尺寸的整数类型转为一个小尺寸的整数类型 (int32 -> int16)
  • 将一个浮点数转为整数,可能会改变数值或丢失精度 (float64 -> int32)
整型

带符号和无符号的不同位整型:int8、int16、int32、int64、uint8、uint16、uint32、uint64

int、uint

rune 通常用于表示一个Unicode码点(等价于 int32

byte 字节内容(**等价于 uint8 **)

*uintptr 一般是写底层用的

浮点型

float32、float64

复数

complex64、complex128

布尔值

true、false

字符串

8位字节序列构成的字符串,约定但不必须是utf-8编码的文本。 字符串可以为空但不能是nil,其值不可变

字符串可以用==和<进行比较;比较通过逐个字节比较完成的,因此比较的结果是字符串自然编码的顺序。

文本字符串通常被解释为采用UTF8编码的Unicode码点(rune)序列

len函数 可以返回一个字符串中的字节数目(不是rune字符数目)

len("汉")  // 3. 中文 utf8 下为三个字节

连接通过 "+"号:

fmt.Println("你" + "好")

Unicode 符号和二进制编码的对应关系;

UTF-8 针对Unicode的可变长度字符编码方式。最长的符号达到6个字节了(汉字一般是3个,还有其他的)

  • 目前最长的符号达到6个字节了
  • 汉字一般3字节,但还有其他的4字节;详见unicode码表
  • mysql中常见的 utf8mb4 是为了兼容宽字节(也就是4个字节)的情况
tempStr := "汉1"
fmt.Printf("rune(char):%q\n", []rune(tempStr))	// rune(char):['汉' '1']
fmt.Printf("rune(hex):%x\n", []rune(tempStr))	// rune(hex):[6c49 31]		-- Unicode 码值
fmt.Printf("bytes(hex):% x\n", []byte(tempStr))	// bytes(hex):e6 b1 89 31	-- UTF-8 编码后

// len 访问时
fmt.Println(len(tempStr)) // 4 => 字节数

// 访问指定偏移量时
fmt.Println(tempStr[2]) // 137 => 字节序访问

// 直接遍历字符串的时候
for _, val := range tempStr {
   
    fmt.Println(val)	// 27721 49 => unicode码值
}

// 上面的三个步骤说明如下:
// 1. 按照一个个字符拆分
// 2. 字符转为 unicode码表
// 3. 使用UTF-8转换为字节序

fmt
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值