笔记概览:
1.基本语法:变量,选择,循环,指针,数组,容器
2.面向接口:结构体,duck typing的概念,组合的思想
3.函数式编程:闭包的概念,多样的例题
4.工程化:资源管理,错误处理,测试和文档,性能调优
5.并发编程:goroutine和channel,理解调度器,多样的立体
Go语言基本语法:
package main
import "fmt"
定义变量:
定义变量,变量名写在前面,类型写在后面
func variable() {
var a int
var s string
fmt.Println(a,s)
}
定义函数:
func main() {
fmt.Println("Hello World")
variable()
variableInitialValue()
variableTypeDeduction()
variableShorter()
}
定义变量,变量名写在前面,类型写在后面,输出的时候可以把类型加上 Printf
func variable() {
var a int
var s string
fmt.Printf("%d %q", a, s)
}
变量赋初值
func variableInitialValue() {
var a int = 3
var s string = "abc"
fmt.Println(a,s)
}
func variableInitialValue() {
var a, b int = 3, 4 (同时给两个变量赋值)(变量定义之后一定要用到,不用的话会报错)
var s string = "abc"
fmt.Println(a, b, s)
}
go可以根据变量值自动判断变量的类型,这样可以去掉变量类型,把不同类型的变量写在一行,如果写上类型的话,只能写同一类型的多个变量
func variableTypeDeduction() {
var a, b , c, s = 3, 4, true, "def"
fmt.Println(a, b, c, s)
}
简单写法,可以把var去掉,用 := 来替代,:= 含义就是定义一个变量
第一次使用变量的时候需要定义,用 var 或者 := ,再次使用这个变量是时候就不需要在用var 或者 := 了
在定义变量的时候尽量使用 :=
func variableShorter() {
a, b , c, s := 3, 4, true, "def"
}
在函数内定义的变量作用域在函数内,我们也可以在函数外定义变量
在函数外定义变量,只能使用var ,不能使用 :=
在函数外定义的变量不是全局变量,它的作用域是包内,比如这几个变量的作用域是 main,因为 package main
go没有全局变量的说法
var aa = 3
var ss = "abcd"
var bb = true
bb := 4(错误)
(定义多个变量时,我们可以把它写到一个括号里)
var (
aa = 3
ss = "abcd"
bb = true
)
变量定义总结:
1.使用var关键字:
var a, b, c bool
var s1, s2 string = "hello", "world"
可以放在函数内,或直接放在包内
不论包内还是函数内,都可以使用var()集中定义变量
2.让编译器自动决定类型:
var a, b, i, s1, s2 = true , false, 3, "hello", "world"
3.使用 := 定义变量:
a, b, i, s1, s2 := true, false, 3, "hello", "world"
:= 只能在函数内使用
内建变量类型:
1.bool,string
2.(u)int, (u)int8, (u)int16, (u)int32, (u)int64, uintptr
(加u是无符号整数,不加是有符号整数,整数有的是规定长度的,比如int8,int16,不规定长度的根据操作系统来,32位系统就是32的长度,以次类推)。
uintptr 是指针类型
3.byte, rune
rune 是32 位的
byte是8位的
4.float32, float64, complex64, complex128
complex指的是复数类型
(回顾复数)
(i会被认为是变量i, 1i会被认为是一个实数)
func euler() {
c := 3 + 4i
fmt.Println(cmplx.Abs(c))
}
func euler() {
fmt.Println(cmplx.Pow(math.E, 1i * math.Pi) + 1)
}
5.强制类型转换
类型转换是强制的,没有隐式类型转换
(在下面的代码中 int() float64() 就属于强制转换)
func triangle() {
var a, b int = 3, 4
var c int
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(c)
}
常量的定义:
可以规定类型,也可以不规定类型,规定的话就是规定的类型,不规定的话就是一个文本形式的,不存在类型转换
在go中常量可以不需要全部大写,按正常的变量写就可以了
const 数值可以作为各种类型使用
func consts() {
const filename string = "abc.txt"
const a, b int = 3, 4
const filename = "abc.txt"
const a, b = 3, 4
(另一种写法)
const (
filename = "abc.txt"
a, b = 3, 4
)
}
使用常量定义枚举类型:
func enums() {
const(
cpp = 0
java = 1
python = 2
golang = 3
)
}
fmt.Println(cpp, java, python, golang)
(iota可以使这个枚举类型自增)
func enums() {
const(
cpp = iota
java
python
golang
)
}
fmt.Println(cpp, java, python, golang)
(iota还可以进行运算)
const (
b = 1 << (10 * iota)
kb
mb
gb
tb
pb
)
(普通枚举类型,自增值枚举类型)
变量定义要点:
变量类型写在变量名之后
编译器可以推测变量类型
没有char , 只有 rune
原生支持复数类型
条件语句:
if用法:
(if的条件是不需要括号的)
func bounded(v int) int {
if v > 100 {
return 100
}else if v < 0 {
return 0
}else {
return v
}
}
(if的条件里可以赋值,if的条件里赋值的变量作用域就在这个if语句里)
func main() {
const filename = "abc.txt"
if contents , err := ioutil.ReadFile(filename) ; err != nil {
fmt.Println(err)
}else{
fmt.Printf("%s\n", contents)
}
}
switch用法:
(switch会自动break,除非fallthrough)
(switch 后面可以没有表达式,直接在case 后面加上)
func eval(a, b int, op string){
var result int
switch op {
case "+":
result = a+b
case "-":
result = a-b
case "*":
result = a*b
case "/":
result = a/b
default:
panic("unsupported operator:" + op)
}
return result
}
循环语句:
for用法:
(for的条件里不需要括号)
(for的条件里可以省略初始条件,结束条件,递增表达式)
sum := 0
for i := 1; i<= 100; i++ {
sum += i
}
(省略初始条件,相当于while)
for ; n>0; n/=2{
lsb := n%2
return strconv.Itoa(lsb) + result
}
(省略初始条件和递增条件)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
(全部省略,就是一个死循环,无限循环)
for {
fmt.Println("abc")
}
要点回顾:
for , if 后面的条件没有括号
if条件里也可以定义变量
没有while
switch不需要break,也可以直接switch多个条件
网友评论