本文继上文 golang笔记01–golang基础配置, 进一步了解 golang 基础语法和相应注意事项。
具体包括 : 变量定义 ,内建变量类型,常量与枚举,条件语句,循环,函数,指针 等基础语法。
变量要点:
1)变量类型写在变量名后面
2)编译器可以推测变量类型
3)没有char,只有rune(32位)
4)原生支持复数类型
package main
import "fmt"
// 包内部的变量,而非全局变量
var (
aa = 3
bb = 4
cc = "cc"
)
func variableZeroValue() {
var a int
var s string
fmt.Printf("%d %q\n", a, s)
}
func variableInitValue() {
var a, b int = 3, 4
var s string = "abc"
fmt.Println(a, b, s)
}
func variableTypeDeduction() {
var a, b, c, s = 3, 4, true, "def"
fmt.Println(a, b, c, s)
}
func variableShorter() {
// := 定义的变量只能在函数内使用
a, b, c, s := 3, 4, true, "def"
b = 5
fmt.Println(a, b, c, s)
}
func main() {
fmt.Println("hello world")
variableZeroValue()
variableInitValue()
variableTypeDeduction()
variableShorter()
fmt.Println(aa, bb, cc)
}
输出:
hello world
0 ""
3 4 abc
3 4 true def
3 5 true def
3 4 cc
常见类型包括:
bool, string
int int8, int16, int32, int64, uintptr
byte, rune(go 的字符类型)
float32 float64 complex64(复数) complex128
强制类型转换,go没有隐式转换
package main
import (
"fmt"
"math"
"math/cmplx"
)
func euler() {
fmt.Println("euler")
c := 3 + 4i
fmt.Println(cmplx.Abs(c))
fmt.Printf("%3f\n", cmplx.Exp(1i*math.Pi)+1)
}
func triangle() {
fmt.Println("triangle")
var a, b int = 3, 4
var c int
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(c)
}
func main() {
fmt.Println("chapter2.2")
euler()
triangle()
}
输出:
chapter2.2
euler
5
(0.000000+0.000000i)
triangle
5
常量:通过 const 来定义
枚举:通过一组const来定义枚举
package main
import "fmt"
func consts() {
// 常量名称一般不大写
const filename = "test.txt"
const a, b = 3, 4
const (
c, d = 5, 6
flag = true
)
fmt.Println(filename, a, b, c, d, flag)
}
func enums() {
const (
cpp = 0
java = 1
python = 2
)
fmt.Println(cpp, java, python)
// 通过iota实现自增值
const (
cpp1 = iota
java1
python1
)
fmt.Println(cpp1, java1, python1)
const (
b = 1 << (10 * iota)
kb
mb
gb
tb
pb
)
fmt.Println(b, kb, mb, gb, tb, pb)
}
func main() {
consts()
enums()
}
输出:
test.txt 3 4 5 6 true
0 1 2
0 1 2
1 1024 1048576 1073741824 1099511627776 1125899906842624
go 中的条件语句主要包括if, else, switch;
if 后面的条件没有括号;
if 条件里面也可以定义变量;
switch 不需要break,也可以直接switch多个条件;
package main
import (
"fmt"
"io/ioutil"
)
func bounded(v int) int {
// if 条件式不需要括号的
if v > 100 {
return 100
} else if v < 0 {
return 0
} else {
return v
}
}
func readFile() {
const filename = "abc.txt"
contents, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("%s", contents)
}
}
func calculator(a, b int, op string) int {
// switch 的 case 会自动 break,不需要单独添加
// 若 switch 中没有表达式,则可以在 case 中增加条件
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
}
func main() {
fmt.Println("chapter 2.4")
fmt.Println(bounded(50))
readFile()
fmt.Println(calculator(1, 15, "+"))
}
golang 中通过 for 实现循环,没有while;
for 后面的条件没有括号;
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"time"
)
func convert2bin(n int) string {
// 省略初始条件
result := ""
for ; n > 0; n /= 2 {
lsb := n % 2
result = strconv.Itoa(lsb) + result
}
return result
}
func printFile(filename string) {
// for 中省略起始 和 递增条件
file, err := os.Open(filename)
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
func forever() {
// 不添加如何内容即为死循环
for {
fmt.Println("abc")
time.Sleep(time.Second * 1)
}
}
func main() {
fmt.Println(convert2bin(5))
fmt.Println(convert2bin(13))
printFile("2.5.txt")
forever()
}
输出:
101
1101
line 001
line 002
abc
abc
......
函数语法要点:
1)返回值类型写在最后面
2)可以返回多个值
3)函数作为参数
4)没有默认参数,可选参数
package main
import (
"fmt"
"math"
"reflect"
"runtime"
)
func eval(a, b int, op string) (int, error) {
switch op {
case "+":
return a + b, nil
case "-":
return a - b, nil
case "*":
return a * b, nil
case "/":
q, _ := div(a, b)
return q, nil
default:
// panic("unsupported operator:" + op)
return 0, fmt.Errorf("unsupported operator: %s" + op)
}
}
func div(a, b int) (q, r int) {
// return a / b, a % b
q = a / b
r = a % b
return q, r
}
func pow(a, b int) int {
return int(math.Pow(float64(a), float64(b)))
}
func sum(numbers ...int) int {
s := 0
for i := range numbers {
s += numbers[i]
}
return s
}
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) ", opName, a, b)
return op(a, b)
}
func main() {
fmt.Println(eval(3, 4, "x"))
fmt.Println(eval(13, 4, "/"))
q, r := div(13, 4)
fmt.Println(q, r)
fmt.Println(apply(pow, 3, 4))
fmt.Println(apply(
func(a int, b int) int {
return int(math.Pow(float64(a), float64(b)))
}, 2, 4))
fmt.Println(sum(1, 2, 3, 4))
}
输出:
0 unsupported operator: %!s(MISSING)x
3 <nil>
3 1
Calling function main.pow with args (3, 4) 81
Calling function main.main.func1 with args (2, 4) 16
10
go 语言函数使用值传递,但使用指针参数可以实现引用的功能;
package main
import "fmt"
func swap(a, b int) {
// 值传递
a, b = b, a
}
func swap_ptr(a, b *int) {
// 指针传递
*a, *b = *b, *a
}
func main() {
fmt.Println("chapter 2.7")
a, b := 3, 4
swap(a, b)
fmt.Println(a, b)
swap_ptr(&a, &b)
fmt.Println(a, b)
}
输出:
chapter 2.7
3 4
4 3
var a float32 = 4.999999
fmt.Println(int(a))
可以使用 decimal 包 来解决精度丢失问题