写在前面的话
18年的时候就想着要学golang, 结果一拖就是1年多, 这19年都已经快过了一半了,想想自己的惰性实在太强,还是得逼自己一把才行,不然20年了估计还是没戏,所以找了一个切入点,最近在网上找到了一个教学视频,叫 Google资深工程师深度讲解Go语言 ,稍微看了一下, 觉得讲的挺好, 是以一个在已经有了别的语言基础上, 作为项目转型首选语言的角度来介绍golang的, 讲到每个语法基本会和其他的语言进行比较, 这样也比较容易记忆.
那么这个系列的学习笔记就根据这个视频的章节来走, 记录一下每个章节里介绍到的golang比较特殊的地方, 便于之后翻看复习和记忆.
希望自己坚持吧 加油加油!
PS:大多数总结的内容和代码都来源于教学视频的PPT和示例代码,少部分来我自己的理解,之后的学习笔记的博客都是一样
第一章 基础语法
定义变量
- 变量类型写在变量名之后
- 使用 var 关键字
var a int // 定义int型的变量a 默认值为0
var a int = 10 // 定义int型变量a 赋初始值为10
var s1, s2 string = "hello", "world" // 定义字符串类型s1,s2并赋初始值
- var 关键字可以放在函数内, 也可以在包内, 一般作用域为包内的变量用var来定义
- 可以使用 var() 来集中定义变量
var (
aa = 3
ss = "kkk"
bb = true
)
- 让编译器自动决定类型
var a, b, i, s1, s2 = true, false, 3, "hello", "world"
- 使用 := 定义变量, 只能在函数内使用
a, b, i, s1, s2 := true, false, 3, "hello", "world"
- 简短变量声明左边的变量可能并不是全部都是刚刚声明的。如果有一些已经在相同的词法域声明过了,那么简短变量声明语句对这些已经声明过的变量就只有赋值行为了。
in, err := os.Open(infile)
// ...
out, err := os.Create(outfile)
- 简短变量声明语句中必须至少要声明一个新的变量,下面的代码将不能编译通过
f, err := os.Open(infile)
// ...
f, err := os.Create(outfile) // compile error: no new variables
内建变量类型
- bool, string
- (u)int, (u)int8, (u)int16, (u)int32, (u)int64, uintptr
- byte, rune(字符型 类似char, 但是长度为4字节)
- float32, float64, complex64, complex128
强制类型转换
- 只能强制转换, 不能隐式转换
var a, b int = 3, 4
var c int = math.Sqrt(a*a + b*b) // 错误
var c int = int(math.Sqrt(float64(a*a + b*b))) // 正确
常量的定义
const filename = "abc.txt"
const 数值可以作为各种类型使用
const a, b = 3, 4
var c int = math.Sqrt(a*a + b*b) // 这里编译就不会像上面强制类型转换的例子报错
使用常量定义枚举类型
- 普通枚举类型
const (
cpp = 0
java = 1
pythod = 2
golang = 3
)
- 自增值枚举类型
const (
cpp = iota
java
pythod
golang
)
// 这里的枚举的数值和上面一样
条件语句 if
- if的条件里不需要括号
- if的条件里可以赋值
- if的条件里赋值的变量的作用域就在这个if语句里
const filename = "abc.txt"
if contents, err := ioutil.ReadFile(filename); err != nil {
fmt.Println(err)
} else {
fmt.Printf("%s\n", contents)
}
条件语句 switch
- switch会自动break,不用打break,除非使用 fallthough
- switch后可以没有表达式,直接在case里面加入条件,类似 if / elseif / elseif/ else
g := ""
switch {
case score < 60:
g = "F"
case score < 80:
g = "C"
case score < 90:
g = "B"
case score <= 100:
g = "A"
}
循环语句 for(没有while, 直接用for代替)
- for的条件里不需要括号
- for的条件里可以省略初始条件,结束条件,递增表达式
// 省略初始条件
func convertToBin(n int) string {
result := ""
for ; n > 0; n /= 2 {
lsb := n % 2
result = strconv.Itoa(lsb) + result
}
return result
}
// 省略初始条件,结束条件
func printFileContents(reader io.Reader) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
// 省略初始条件,结束条件,递增表达式
// 相当于while(true)
func forever() {
for {
fmt.Println("abc")
}
}
函数
- 返回值类型写在最后面
- 可返回多个值
func test(a int, b string) ( success bool, errorInfo error, result int ) {
return true, fmt.Errorf(b), a
}
- 函数可以作为参数
func apply(op func(int, int) int, a, b int) int {
...
}
- 没有默认参数, 可选参数
- 只有可变参数列表
func sum(numbers ...int) int {
s := 0
for i := range numbers {
s += numbers[i]
}
return s
}
指针
- 指针不能运算(指针地址偏移运算)
参数传递
- 只有值传递一种方式
- 需要引用传递可以把参数类型定为指针类型
一些小技巧
- Printf 格式化
- 附上一篇详解 Printf格式化输出、Scanf格式化输入详解
%d 十进制整数
%x, %o, %b 十六进制,八进制,二进制整数。
%f, %g, %e 浮点数: 3.141593 3.141592653589793 3.141593e+00
%t 布尔:true或false
%c 字符(rune) (Unicode码点)
%s 字符串
%q 带双引号的字符串"abc"或带单引号的字符'c'
%v 变量的自然形式(natural format)
%T 变量的类型
%% 字面上的百分号标志(无操作数)
- 获取函数名
func apply(op func(int, int) int, a, b int) int {
p := reflect.ValueOf(op).Pointer()
opName := runtime.FuncForPC(p).Name()
fmt.Printf("Calling function %s with args "+
"(%d, %d)\n", opName, a, b)
return op(a, b)
}
- 利用返回值做值交换
func swap(a, b int) (int, int) {
return b, a
}
- 可以通过 ‘_’ 来省略变量(因为Golang申明了的变量必须要有引用,不然就会编译报错)
// 调用上面的swap方法
a, _ = swap( 1, 2 )