1. 基礎語法
阿新 • • 發佈:2018-12-01
一. 變數定義
package main import "fmt" var ( // 函式外的變數 並非全域性變數, 而是包內變數 aa = 3 ss = "kkk" ) // 函式外面 不能用:=定義變數 func variableZeroValue() { var a int var s string // go語言的變數 在定義的時候就會有一個 初始值 fmt.Printf("%d %q\n", a, s) } func variableInitialValue() { var a, b int = 3, 4 var s string = "abc" fmt.Println(a, b, s) } func varibleTypeDeduction() { 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" // := 和 var = 一個意思, 只能在第一次定義變數時用 b = 5 fmt.Println(a, b, c, s) } func main() { fmt.Println("Hello world") variableZeroValue() variableInitialValue() varibleTypeDeduction() variableShorter() fmt.Println(aa, ss) }
二. 內建變數型別
- bool, string
- (u)int, (u)int8, (u)int16, (u)int32, (u)int64, 帶u表示無符號整型
- uintptr ptr表示指標
- byte
- rune 字元型 32位 go中不叫char,優化了char, 避免了很多坑
- float32, float64
- complex64, complex128 複數
複數演示
func euler() { c := 3 + 4i //定義複數 fmt.Println(cmplx.Abs(c)) // 得到5 fmt.Println( cmplx.Exp(1i*math.Pi), // 或者 cmplx.Pow(math.E, 1i*math.Pi)) // i不會解釋為複數, 需要寫成1i //(-1+1.2246467991473515e-16i) (-1+1.2246467991473515e-16i) // 去掉尾巴 可以使用 fmt.Printf("%0.3d", cmplx.Exp(1i*math.Pi)) }
go只有強制型別轉化
func trangle() {
var a, b int = 3, 4
var c int
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(c)
// 如果寫 var c int = math.Sqrt(a*a, b*b) 會失敗, go只能強制型別轉化, 無法自動轉
}
三. 常量和列舉
常量
- 例如 const filename = "abc.txt"
- const 型別可以作為各種型別使用
func consts() { const filename = "abc.txt" const a, b = 3, 4 var c int c = int(math.Sqrt(a*a + b*b)) //const 型別可以作為各種型別使用,這裡會作為float fmt.Println(filename, c) }
列舉
- 普通列舉型別
- 自增值列舉型別
func enums() {
//const(
// cpp = 0
// java = 1
// python = 2
// golang = 3
//)
// 可以簡化為
const (
cpp = iota
_ // _表示跳過 1
python //2
golang //3
javascript //4
)
fmt.Println(cpp, javascript, python, golang) // 0, 4, 2,3
// iota更復雜的用法, 可以作為自增值的 種子
const (
b = 1 << (10*iota)
kb
mb
gb
tb
pb
)
fmt.Println(b, kb, mb, gb, tb, pb) //1 1024 1048576 1073741824 1099511627776 1125899906842624
}
四. 條件語句
if
import (
"io/ioutil"
"fmt"
)
func ifexample() {
const filename = "abc.txt"
// 常規用法
//contents, err = ioutil.ReadFile(filename)
//
//if err != nil {
// fmt.Println(err)
//} else {
// fmt.Printf("%s\n", contents)
//}
// if後面可以跟 多個語句的
// if語句中可以定義變數
if contents, err := ioutil.ReadFile(filename); err == nil {
fmt.Println(string(contents))
} else {
fmt.Println("cannot print file contents:", err)
}
// if後的變數只在 if範圍內起作用
}
switch
- switch 會自動break, 如果不想break, 加fallthrough
func grade(score int) string {
g := ""
switch {
case score < 60 && score >= 0:
g = "F"
case score < 80:
g = "C"
case score < 90:
g = "B"
case score <= 100:
g = "A"
default:
panic(fmt.Sprintf("Wrong score: %d", score)) // panic會終斷程式的執行, 並報錯
}
return g
}
func main() {
fmt.Println(
grade(0),
grade(55),
)
}
五. 迴圈
- for 的條件裡不加括號
- for的條件裡可以省略初始條件, 結束條件, 遞增表示式
sum := 0
for i:= 1; i <= 100; i++ {
sum += 1
}
實際舉例
package main
import (
"fmt"
"strconv"
"os"
"bufio"
)
func convertToBin(n int) string { // 10進位制轉2進位制
result := ""
for ; n > 0; n /= 2 {
lsb := n%2
result = strconv.Itoa(lsb) + result
}
if result=="" {
result = "0"
}
return result
}
func printFile(filename string) {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() { // 這裡的for 沒有起始條件和遞增條件 只有結束條件 就相當於while go語言中沒有while
fmt.Println(scanner.Text())
}
}
func forever() {
for { // 沒有起始條件, 沒有遞增條件, 也沒有結束條件 相當於死迴圈
fmt.Println("abc")
}
}
func main() {
fmt.Println(
convertToBin(5), // 101
convertToBin(13), // 1101
convertToBin(0), // 0
)
printFile("abc.txt")
}
六. 函式
- 函式名在前 , 返回值型別在後, 引數也是如此
- 可以將函式作為引數
- 可以返回多個值
- go沒有 預設引數, 可選引數, 過載等複雜操作, 只有可變引數列表...
- go的匿名函式 就是 直接省略函式名
package main
import (
"fmt"
"math"
"reflect"
"runtime"
)
func eval(a, b int, op string) (int, error) {// error返回錯誤
switch op {
case "+":
return a + b, nil // nil 是沒有被 賦值的變數 函式 類。。。的預設初始值, 類似空指標
case "-":
return a - b, nil
case "*":
return a * b, nil
case "/":
q, _ := div(a, b) // 有兩個返回值, 但只接收一個返回值
return q, nil
default:
return 0, fmt.Errorf(
"unsupported operation: %s", op)
}
}
// 帶餘數的除法
func div(a, b int) (q, r int) { // 可以返回多值, 並且可以對返回值取名, 編輯器會用改名接收返回值
return a / b, a % b
}
func apply(op func(int, int) int, a, b int) int { // 傳入引數op 是函式
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 sum(numbers ...int) int { // ...引數列表, 可以傳任意數量的int
s := 0
for i := range numbers {
s += numbers[i]
}
return s
}
func swap(a, b int) (int, int) {
return b, a
}
func main() {
fmt.Println("Error handling")
if result, err := eval(3, 4, "x"); err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println(result)
}
q, r := div(13, 3) // 接收返回值
fmt.Printf("13 div 3 is %d mod %d\n", q, r)
fmt.Println("pow(3, 4) is:", apply(
func(a int, b int) int { // 使用go語言的 匿名函式
return int(math.Pow(
float64(a), float64(b)))
}, 3, 4))
fmt.Println("1+2+...+5 =", sum(1, 2, 3, 4, 5))
a, b := 3, 4
a, b = swap(a, b)
fmt.Println("a, b after swap is:", a, b)
}
七. 指標
- 指標不能運算
- go的函式引數都是值傳遞, 想要達到引用傳遞的效果, 可以使用指標
func swap(a, b *int){
*a, *b = *b, *a
}
func main() {
a, b := 3, 4
swap(&a, &b)
}
交換值有更好的方法
func swap(a, b int) (int, int) {
return b, a
}
func main() {
a, b := 3, 4
b, a = swap(a, b)
}