【Go】Golang 学习笔记

1. 入门

  • 1.1 Hello, world

package main

import (mb
    "fmt"
)

func main() {
    fmt.Println("Hello, go")
}
  • 1.2 fmt.Print 和 fmt.Println

    • 可以传若干个参数,之间用逗号分开。
    • 参数可以是字符串、数字、数学表达式等等。
    • Println 比 Print 多输出一个回车。
  • 1.3 fmt.Printf 格式化打印

    • 类似 C 语言里的 printf,第一个参数必须是字符串
    • 包含了像 %v 这样的格式化动词,值由第二个参数代替
  • 1.4 fmt.Printf 对齐文本

    • 在格式化动词里指定宽度,就可以对齐文本。例如,%4v,就是向左填充到足够4个宽度
    • 正数,向左填充空格
    • 负数,向右填充空格
package main

import (
    "fmt"
)

func main() {
    fmt.Printf("%-15v $%4v\n", "SpaceX", 94)
    fmt.Printf("%-15v $%4v\n", "Virgin Galactic", 100)
}

2. 常量和变量

  • const,用来声明常量,常量的值不可改变
  • var,用来声明变量,想要使用变量必须先声明
  • 2.1 同时声明多个变量

func main() {
    //第一种直接声明
    var distance = 56000000
    var speed = 100800

    //第二种,用括号
    var (
        distance = 56000000
        speed = 100800
    )

    //第三种,用逗号
    var distance, speed = 56000000, 100800

    //常量也一样
    const hoursPerDay, minutesPerHour = 24, 60
}
  • 2.2 运算符

    • 有加减乘除,+=/-=/*= 等,与其他语言一致
    • 有++,但是只有 count++,没有++count
  • 2.3 随机数

    • 使用 rand 包,可以生成伪随机数
    • 例如,Intn 可以返回一个指定范围的随机整数 - [0, n)
    • import 的路径是“math/rand”
    • rand.Seed(time.Now().UTC().UnixNano())

3. 循环与分支

  • 3.1 Boolean 类型

    • 某些语言(例如 JS)会把""字符串当作 false,其他字符串当作 true;
    • 但是 Go 语言不行,只有 true 是真,false 是假。
  • 3.2 strings.Contains 函数

    • 用于判断是否包含子字符串。
  • 3.3 比较运算符

    • ==、<=、<、!=、>=、>
  • 3.4 逻辑运算符

    • ||、&&、!
    • Go 语言里同样有短路逻辑
  • 3.5 switch case 命令

    • 不用写 break
    • 多个 case 可以用逗号隔开
    • 还有 fallthrough 关键字,可以穿过执行下一个 case 的 body 部分。
func main() {
    var command = "go inside"

    switch command {
    case "go east":
        fmt.Println("You head further up the mountain.")
    case "enter cave", "go inside":
        fmt.Println("You find yourself in a dimly lit cavern.")
    case "read sign":
        fmt.Println("The sign reads 'No Minors'.")
    default:
        fmt.Println("Didn't quite get that.")
    }
}
  • for 循环

    • 带一个条件 = while 循环
    • 带初始化,判断,赋值 = for 循环

4. 变量与作用域

  • 4.1 作用域

    • 变量被声明后即进入了作用域
    • Go 里的作用域就是 {} 之间的部分
    • 作用域的好处就是,可以在不同作用域声明同名变量,而不至于冲突
  • 4.2 短声明

    • count := 10
    • 短声明可以在不能用var的地方,声明变量
  • 4.3 package 作用域

    • main 函数以外定义的变量
    • 对本 package 内所有函数可见
    • 不能用短声明定义 package 作用域的变量,得用var

5 实数

  • 5.1 浮点型变量

下面三个语句结果都是一样的:

days := 365.2425
var days = 365.2425
var days float64 = 365.2425

只要数字含有小数部分,那么它的类型就是float64

双精度float64,其他语言叫做double

单精度float32,其他语言叫做float

使用 PrintPrintln 打印浮点数时,默认尽可能多打印几位小数

如果你不想这样,那么你应该使用 Printf 函数

third := 1.0 / 3
fmt.Println(third)
fmt.Printf("%v\n", third)
fmt.Printf("%f\n", third)
fmt.Printf("%.3f\n", third)
fmt.Printf("%4.2f\n", third)
  • 5.2 整数

    • 8种整数类型
      • int8、uint8、int16、uint16、int32、uint32、int64、uint64
      • 类型与CPU架构无关
    • 而 int 和 uint 是针对目标设备优化的类型
      • 在树莓派 2、比较老的移动设备上,int 和 uint 都是32位的
      • 在比较新的计算机上,int 和 uint 都是 64 位的
      • int 和 uint 不是8种类型的别名,是另外的2种类型。
    • 整数类型的最大、最小值常量:
      • math.MaxInt16math.MinInt64
      • 而 int 和 uint,可能是 32 或者 64 位的,所以没有系统定义的最大/小值。
  • 5.3 非常大的数

    • 如果没有为指数形式的数值指定类型的话,那么 Go 将会将它视作 float64 类型
    • 对于较大的整数(超过10^18):big 包的 big.Int
    • 对于任意精度的浮点类型,big.Float
    • 对于分数,big.Rat
import (
    "fmt"
    "math/big"
)

func main() {
    lightSpeed := big.NewInt(299792)
    secondsPerDay := big.NewInt(86400)
    fmt.Println(lightSpeed, secondsPerDay)

    distance := new(big.Int)
    distance.SetString("2400000000000000000000000000000000000", 10)
    fmt.Println(distance)

    seconds := new(big.Int)
    seconds.Div(distance, lightSpeed)

    days := new(big.Int)
    days.Div(seconds, secondsPerDay)

    fmt.Println("That is", days, "days of travel at light speed.")
}

6 字符串

  • 6.1 字符串字面值

    • 字符串字面值可以包括转义字符,例如 \n
    • 如果你确实想得到\n而不是换行,可以使用``
  • 6.2 字符,code points,runes,bytes

    • Unicode 联盟为超过 100 万个字符分配了相应的数值,这个数叫做 code point
      • 例如:65 代表 A,128515 代表 😃
    • 为了表示这样的 unicode code point,Go 语言提供了 rune 这个类型,它是 int32 的一个类型别名
    • 而 byte 是 uint8 类型的别名,目的是用于二进制数据。
  • 6.3 打印

    • 如果想打印 字符 而不是 数值,那么可以使用 %c
    • 任何整数类型都可以使用 %c 打印,但是 rune 意味着该数值表示了一个字符
    • 字符字面值使用单引号 '' 括起来
    • 如果没指定字符类型的话,那么 Go 会推断它的类型为 rune
    • 字符字面值也可以用 byte 类型
  • 6.4 Go 内置函数

    • len 是 Go 语言的一个内置函数,统计的是 byte 数
    • 对于多字节的文字如:西班牙语、汉语等,可能长度不对
message := "你好"
fmt.Println(len(message)) //6
  • 如何支持西班牙语、俄语、汉语等?
    • 把字符解码成 rune 类型,然后再进行操作。
  • 使用 unicode/utf8 包,它提供可以按 rune 计算字符串长度的方法:DecodeRuneInString
fmt.Println(len(message), "bytes") //6
fmt.Println(utf8.RuneCountInString(message), "runes") //2
c, size := utf8.DecodeRuneInString(message)
fmt.Printf("First rune: %c %v bytes", c, size)

7 类型转换

  • 7.1 类型不能混着用

    • 拼接字符串和Int型是会报错的
    • 整型和浮点类型也不能混着用,加减乘除是会报错的
    • 类型转换如下:
age := 41
marsAge := float64(age)

earthDays := 365.2425
fmt.Println(int(earthDays)) //会被截断

c := string(65)
fmt.Println(c) //A
  • 无符号和有符号类型间也需要转换
  • 不同大小的整数类型之间也需要转换
  • 想把数值转化为 string,它的值必须能转化为 code point
  • strconv 包的 Itoa 函数就可以做这件事
    • Itoa 是 Integer to ASCII 的意思
  • 另外一种把数值转化为 string 的方式是使用 fmt.Sprintf 函数,
  • 和 Printf 略类似,但是会返回一个 string

8 函数

  • 8.1 声明与调用

func Intn(n int) int //func关键字 函数名(变量名 变量类型) 函数返回值
num := rand.Intn(10) // 包名.函数名(传参)
  • 8.2 函数声明

    • 在 Go 里,大写字母开头的函数、变量或其他标识符都会被导出,对其他包可用
    • 小写字母开头的就不行。
  • 8.3 多个返回值

    • 多个返回值需要用括号括起来
func Atoi(s string) (i int, err error)
countdown, err := strconv.Atoi("10")
  • 8.4 可变参数

func Println(a ...interface{}) (n int, err error)
  • 8.5 声明新类型

    • 关键字 type 可以用来声明新类型
type celsius float64
var temperature celsius = 20
  • 因为仅仅是起别名,所以celsius还是可以和float64一起运算
  • 为什么要声明新类型?因为可以极大提高代码可读性和可靠性
  • 8.6 通过方法添加行为

    • 在 C#、Java 里,方法属于类
    • 在 Go 里,它提供了方法,但是没提供类和对象
    • Go 比其他语言的方法要灵活
    • 可以将方法与同包中声明的任何类型相关联,但不可以是 int、float64 等预声明的类型进行关联
type celsius float64
type kelvin float64

func (k kelvin) celsius() celsius {
    return celcius(k - 273.15)
}
  • 变量调用 变量名.方法()
import "fmt"

func main() {
    var k kelvin = 294.0
    var c celsius

    c = kelvinToCelsius(k)
    c = k.celsius()

    fmt.Println(c)
}

type kelvin float64
type celsius float64

func kelvinToCelsius(k kelvin) celsius {
    return celsius(k - 273.15)
}

func (k kelvin) celsius() celsius {
    return celsius(k - 273.15)
}
  • 8.7 一等函数

    • 在 Go 里,函数是一等公民。
    • 可以将函数赋给变量
    • 将函数作为参数传递给函数
  • 8.8 声明函数类型

    • 为函数声明类型有助于精简和明确调用者的代码。
type sensor func() kelvin

func measureTemperature(samples int, s func() kelvin) //可以简写为
func measureTemperature(samples int, s sensor)
  • 8.9 闭包和匿名函数

    • 匿名函数就是没有名字的函数,在 Go 里也称作 函数字面值(function literal)
//匿名函数
var f = func() {
    fmt.Println("Dress up for the masquerade.")
}

//立即执行
func main() {
    func() {
        fmt.Println("Functions anonymous")
    }()
}

//闭包
type kelvin float64
type sensor func() kelvin

func realSensor() kelvin {
    return 0
}

func calibrate(s sensor, offset kelvin) sensor {
    return func() kelvin {
        return s() + offset
    }
}

func main() {
    sensor := calibrate(realSensor, 5)
    fmt.Println(sensor())
}

9 数组

  • 9.1 访问数组元素

var planets [8]string

planets[0] = "Mercury"
planets[1] = "Venus"
planets[2] = "Earth"

earth := planets[2]
fmt.Println(earth)
fmt.Println(len(planets))
  • 9.2 数组越界

    • Go 编译器在检测到对越界元素的访问时会报错
    • 如果 Go 编译器在编译时未能发现越界错误,那么程序在运行时会出现 panic
  • 9.3 使用复合字面值初始化数组

    • 复合字面值(composite literal)是一种给复合类型初始化的紧凑语法
//字面值初始化
dwarfs := [5]string{"Ceres", "Pluto", "Haumea", "Makemake", "Eris"}
//自动计算长度
dwarfs := [...]string{"Ceres", "Pluto", "Haumea", "Makemake", "Eris"}
//range 遍历数组
for i, dwarf := range dwarfs {
    fmt.Println(i, dwarf)
}
  • 9.4 数组的复制

    • 无论数组赋值给新的变量还是将它传递给函数,都会产生一个完整的数组副本
    • 数组也是一种值,函数通过值传递接受参数。所以数组作为函数的参数,非常低效
    • 数组的长度也是数组类型的一部分
      • 尝试将长度不符的数组作为参数传递,将会报错
    • 所以:
      函数一般使用 slice 而不是数组作为参数
  • 9.5 数组的数组

var board [8][8]string
board[0][0] = "r"
board[0][7] = "r"
for column := range board[1] {
    board[1][column] = "p"
}
fmt.Print(board)

10 Slice 切片

  • 10.1 Slice 指向数组的窗口

    • 切分数组不会导致数组被修改,它只是创建了指向数组的一个窗口或视图
      这种视图就是 slice 类型
planets[0:4]  //前4个元素
planets[4:6]  //4-5 两个元素
  • 10.2 Slice 的默认索引

    • 忽略掉 slice 的起始索引,表示从数组的起始位置进行切分
    • 忽略掉 slice 的结束索引,相当于使用数组的长度作为结束索引
    • slice 索引不能是负数
    • 如果同时省略掉起始和结束索引,那就是包含数组所有元素的一个 slice
    • 切分数组的 slice 也可以用于切分字符串(索引代表字节数而不是rune
  • 10.3 Slice 的复合字面值

    • Go 里面很多函数都倾向于使用 slice 而不是数组作为参数
    • 想要获得与底层数组相同元素的 slice,那么可以使用 [:] 进行切分
    • 切分数组并不是创建 slice 唯一的方法,可以直接声明 slice:例如[]string
  • 10.4 带方法的切片

    • 在 Go 里,可以将 slice 或数组作为底层类型,然后绑定其它方法
type StringSlice []string
func (p StringSlice) Sort() {
    //function body
}

11 更大的 Slice

  • 11.1 append 函数

    • append 函数也是内置函数,可以将元素添加到 slice 里面
dwarfs := []string{"Ceres", "Pluto", "Haumea", "Makemake", "Eris"}
dwarfs = append(dwarfs, "Orcus")
dwarfs = append(dwarfs, "Salacia", "Quaoar", "Sedna")
fmt.Println(dwarfs)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容