learn go
Intro
Go 語言是由 Google 開發的開放原始碼項目,目的之一為了提高開發人員的程式設計效率。 Go 語言語法靈活、簡潔、清晰、高效。它對的並發特性可以方便地用於多核處理器 和網絡開發,同時靈活新穎的類型系統可以方便地撰寫模組化的系統。Go 可以快速編譯, 同時具有記憶體垃圾自動回收功能,並且還支持運行時反射。Go 是一個高效、靜態類型, 但是又具有解釋語言的動態類型特徵的系統級語法。
這邊有兩個可以選擇
- download go
- GVM unix only
GVM 會自動添加 script 到 ~/.bashrc
, 但是筆者使用 fish shell
add gvm.fish
to ~/.config/fish/functions/gvm.fish
content
function gvm
bass source ~/.gvm/scripts/gvm ';' gvm $argv
end
Example
HelloWorld
package main
import "fmt"
func main() {
fmt.Println("Hello, World")
}
go run helloworld.go
golang 與 C 概念類似,一個 program 中只能有一個 main import 方面則與 Python 有些類似
兩種方式 run program
go run program.go
compile (save in temporary dir)and rungo build program.go; ./program
在 local build 出 exectable file, and execute
more print
package main
import "fmt"
func main() {
// math
fmt.Println("1 + 1 = ", 1+1)
fmt.Println("1 - 1 = ", 1-1)
fmt.Println("1 * 1 = ", 1*1)
fmt.Println("1 / 1 = ", 1/1)
fmt.Println("1 % 1 = ", 1%1)
// string
fmt.Println("\"Hello, Wolrd\" have ", len("Hello, World"), "words")
// accesss particular character in string
fmt.Println("Hello, World"[1])
// concate
fmt.Println("Hello, " + "World")
//bool
fmt.Println(true && true)
fmt.Println(true && false)
fmt.Println(true || true)
fmt.Println(true || false)
fmt.Println(!true)
fmt.Println(!false)
}
Variables_Types
用 var 來定義變數,跟其他語言不大箱同的是,Go 必須將型態宣告寫在後面。
Basic types
- bool
- string
- int, int8, int16, int32, int64
- uint, uint8, uint16, uint32, uint64, uintptr
- byte // alias for uint8
- rune // alias for int32, represents a Unicode code point
- float32 float64
- complex64, complex128
初始化變數
如果要同時宣告不同的變數,也可以用小括弧把變數括起來,但是一定要換行。
package main
import "fmt"
var x, y, z int
var yes, no bool
func main() {
fmt.Println(x, y, z, c, yes, no)
}
package main
import "fmt"
var (
x int
y int
z int
c bool
yes bool
no bool
)
func main() {
fmt.Println(x, y, z, c, yes, no)
}
定義變數時可以直接賦予初始值,變數與賦予的值要互相對應。如果有初始化的話,型別就可以省略;變數會直接取用初始化的類型
package main
import "fmt"
var x, y, z int = 1, 2, 3
var yes, no = true, false
func main() {
fmt.Println(x, y, z, yes, no)
}
短變數宣告
package main
import "fmt"
var x, y, z int = 1, 2, 3
yes, no := true, false
func main() {
fmt.Println(x, y, z, yes, no)
}
var a // 不定型別的變數
var a int // 宣告成 int
var a int = 10 // 初始化同時宣告
var a, b int // a 跟 b 都是 intvar a, b = 0, ""
var a int , b string
a := 0
a, b, c := 0, true, "tacolin" // 這樣就可以不同型別寫在同一行
var(
a bool = false // 記得要不同行,不然會錯
b int
c = "hello"
)
強制轉型
浮點數 複數包涵兩種型態 float32、float64。 與其他語言相同, Go 當然也可以用浮點數。 要注意的是,如果初始化的時候沒有加小數點會被推斷為整數,另外初始化的時候沒有指定型態的話,會被自動推斷為 float64。 float64 在 Go 語言相當於 C 語言的 Double,且 float32 與 float64 是無法一起計算的,需要強制轉型。
// 這是強制轉型
轉型型態(變數)
package main
import "fmt"
func main() {
var floatValue float64
floatValue = 7.0
var floatValue2 = 3.0
fmt.Println("7.0/3.0 =", floatValue/floatValue2)
var test float64
var test2 float32
test = 1.1
test2 = 2.2
fmt.Println("test + test2 =", float32(test) + test2)
}
string
package main
import "fmt"
func main() {
var x string = "Hello, World"
fmt.Println(x)
fmt.Println(len("Hello World"))
fmt.Printf("%c",x[1])
}
package main
import "fmt"
func main() {
var x string
x = "first"
fmt.Println(x)
x = x + "second"
fmt.Println(x)
}
bool
如果是初始化讓 Go 自動判斷型態的型態會是 false,而不會是 true
package main
import "fmt"
func main() {
var a bool
a = true
fmt.Println("a =", a)
b := false
fmt.Println("b =", b)
fmt.Println(true && true)
fmt.Println(true && false)
fmt.Println(true || true)
fmt.Println(true || false)
fmt.Println(!true)
}
複數
complex64, complex128
如果是初始化讓 Go 自動判斷型態的型態會是 complex128,而不會是 complex64
package main
import "fmt"
func main() {
var complexValue complex64
complexValue = 1.2 + 12i
complexValue2 := 1.2 + 12i
complexValue3 := complex(3.2, 12)
fmt.Println("complexValue =", complexValue)
fmt.Println("complexValue2 =", complexValue2)
fmt.Println("complexValue3 =", complexValue3)
fmt.Println("complexValue3 實數 =", real(complexValue3))
fmt.Println("complexValue3 虛數 =", imag(complexValue3))
}
Scope
以下兩個範例 執行起來結果是相同 然而 Scope 看到的卻是不同
這邊 variable x
只存在 main
package main
import "fmt"
func main() {
var x string = "Hello, World"
fmt.Println(x)
}
這邊 variable x
是全域變數
package main
import "fmt"
var x string = "Hello, World"
func main() {
fmt.Println(x)
}
func f() {
fmt.Println(x)
}
這邊再舉另外一個例子 編譯時就會發生錯誤 .\main.go:11: undefined: x
variable x
是區域變數 只存在 main function
, f function
看不到 main 的內容, 而 Println
卻要使用 x
, 從而得到 undefined: x
package main
import "fmt"
func main() {
var x string = "Hello, World"
fmt.Println(x)
}
func f() {
fmt.Println(x)
}
Constant
const 使用方式與 C 相同
package main
import "fmt"
func main() {
const x string = "Hello, World"
fmt.Println(x)
}
package main
import "fmt"
func main() {
const x string = "Hello, World"
fmt.Println(x)
x = "Some other string"
// this will cause error, reassign to a const var
}
Exercises
接收使用著輸入數字 輸出數字的兩倍
package main
import "fmt"
func main() {
fmt.Print("Enter a number: ")
var input float64
fmt.Scanf("%f", &input)
output := input * 2
fmt.Println(output)
}
Celsius to Fahrenheit
package main
import "fmt"
func main() {
fmt.Print("Enter a Celsius degree: ")
var input float64
fmt.Scanf("%f", &input)
output := (input + 40) * 1.8 - 40
fmt.Printf("current temperature Celsius: %f to Fahrenheit: %f", input, output)
}
Feets to Meters
package main
import "fmt"
func main() {
fmt.Print("Enter a feet length: ")
var input float64
fmt.Scanf("%f", &input)
output := input * 0.3048
fmt.Printf("current feets: %f to meters: %f", input, output)
}
Flow
for loop
package main
import "fmt"
func main() {
for i := 1; i <= 10; i++ {
fmt.Println(i)
}
}
跟 C 或者 Java 中一樣,可以讓前置、後置語句為空
package main
import "fmt"
func main() {
i := 1
for i <= 10 {
fmt.Println(i)
i = i + 1
}
}
for 也是 go 的 while loop
無窮迴圈
package main
func main() {
for {
}
}
break, continue
break if i is 7
package main
import "fmt"
func main() {
i := 1
for i <= 10 {
if i == 7 {
break
}
else if i % 2 == 0 {
fmt.Println(i)
}
i = i + 1
}
}
loop 1 to 10, print odd number
package main
import "fmt"
func main() {
for i := 0; i < 10; i++ {
if i % 2 == 0 {
continue
}
fmt.Println(i)
}
}
if
package main
import "fmt"
func main() {
for i := 1; i <= 10; i++ {
if i % 2 == 0 {
fmt.Println(i, "even")
}
else {
fmt.Println(i, "odd")
}
}
}
package main
import (
"fmt"
"math"
)
func sqrt(x float64) string {
if x < 0 {
return sqrt(-x) + "i"
}
return fmt.Sprint(math.Sqrt(x))
}
func main() {
fmt.Println(sqrt(2), sqrt(-4))
}
跟 for
一樣, if
語句可以在條件之前執行一個簡單的語句。
由這個語句定義的變數的作用範圍僅在 if
範圍之內。
package main
import (
"fmt"
"math"
)
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
return lim
}
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 20),
)
}
swtich
Switch 是比 if 更有閱讀性的控制結構,跟 C 語言不同的是他不需要 break
來跳出
如果使用 fallthrough
關鍵字,會執行下一個 Case
package main
import "fmt"
func main() {
fmt.Print("Enter a int number(1-5): ")
var input int
fmt.Scanf("%d", &input)
switch input {
case intput < 0 :
fmt.Println("small than zero")
case 0: fmt.Println("Zero")
case 1: fmt.Println("One")
case 2: fmt.Println("Two")
case 3: fmt.Println("Three")
case 4: fmt.Println("Four")
case 5: fmt.Println("Five")
case 6, 7, 8:
fallthrough
default: fmt.Println("Unknown Number")
}
}
Array
Go 語言還有其它種內建的型態
- 陣列
- 切片
- Map
陣列
var x [5]int
宣告一個 int array 長度為 5, 值默認為 0
var x [5]int
y := [5]float64{ 98, 93, 77, 82, 83 }
z := [5]float64{
98,
93,
77,
82,
83,
}
package main
import "fmt"
func main() {
var x [5]int
x[4] = 100
fmt.Println(x)
}
output
[0 0 0 0 100]
總和一個 list 的值
package main
import "fmt"
func main() {
var x [5]float64
x[0] = 98
x[1] = 93
x[2] = 77
x[3] = 82
x[4] = 83
var total float64 = 0
for i := 0; i < 5; i++ {
total += x[i]
}
fmt.Println(total / 5)
這個範例假如你的 array 使用 int , total 使用 float64
你需要注意型態轉換
package main
import "fmt"
func main() {
var x [5]int
x[0] = 98
x[1] = 93
x[2] = 77
x[3] = 82
x[4] = 83
var total float64 = 0
for i := 0; i < len(x); i++ {
total += float64(x[i])
}
fmt.Println(total / float64(len(x)))
}
使用 range
package main
import "fmt"
func main() {
var x [5]float64
x[0] = 98
x[1] = 93
x[2] = 77
x[3] = 82
x[4] = 83
var total1 float64 = 0
// for loop through array, like python enumerate(list)
for i, value := range x {
total1 += value
fmt.Println(i, value)
}
fmt.Println(total1 / float64(len(x)))
// for loop through array
// use under_score if we dont need index
for _, value := range x {
total1 += value
}
fmt.Println(total1 / float64(len(x)))
}
Slices
Function
package main
import "fmt"
func add(x int, y int) int {
return x + y
}
func main() {
fmt.Println(add(42, 13))
}
package main
import (
"fmt"
"math"
"math/rand"
)
func main() {
fmt.Println("My favorite number is", rand.Intn(10))
fmt.Println(math.Pi)
}
multi result
package main
import "fmt"
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("hello", "world")
fmt.Println(a, b)
}