宏觀, 安裝, 配置, 工程命令, 標準命令, 語法
意味著版本與開發速度上的快速, 回顧看看C/C++ JAVA的歷史, 他們起初就不是開源
降低直譯式語言所需要的型別檢查成本
其實叫做跨平台支援......
自動, 甚至允許手動
可以先理解成比C語言的pthread輕量幾十倍的執行緒
goroutine, channel(後面會提)
同時具備 物件導向 函數編程
無繼承層次的輕量級物件導向
非侵入式接口(利於測試)
函數類型叫做第一等類性(後面會說明)
惰性求值
依賴管理明確
gc的能力使你不用過度干涉記憶體管理 大幅降低原始碼長度 開發效率提高
還要我說嗎?(去用Scala吧)
我看$不爽可以吧XD
效能
運行速度還不及
不然等著創造坑自己踩進去吧
Hello World
package main
import "fmt"
func main() {
fmt.Printf("Hello World!\n")
}
變數宣告
var x string = "Hello World" var y string y = "Hello World" z := "Hello World"
流程控制
// for
i := 1
for i <= 10 {
fmt.Println(i)
i = i + 1
}
// also for
for i := 1; i <= 10; i++ {
fmt.Println(i)
}
// add if
for i := 1; i <= 10; i++ {
if i%2 == 0 {
fmt.Println(i, "even")
} else {
fmt.Println(i, "odd")
}
}
// switch
switch i {
case 0:
fmt.Println("Zero")
case 1:
fmt.Println("One")
陣列
// int array
var x [5]int
x[4] = 100
fmt.Println(x) //auto fill 0 with non-assignment
// go through array
var y [5]float64
y[0] = 98
y[1] = 93
y[2] = 77
y[3] = 82
y[4] = 83
var total float64 = 0
for i := 0; i < len(y); i++ {
total += y[i]
}
fmt.Println("Total =", total)
fmt.Println("Average =", total/float64(len(y))) //Mind len(y) is int
// slice不固定大小的陣列( have append copy function....etc)
z := make([]float64, 4, 10)
fmt.Println(z)
fmt.Println(y[1:4]) // same as python
//append
fmt.Println(append(z, 100, 200, 300, 400, 555, 666, 777, 888))
// Map, need memory malloc by using make
elements := make(map[string]string)
elements["H"] = "Hydrogen"
elements["He"] = "Helium"
elements["Li"] = "Lithium"
elements["Be"] = "Beryllium"
elements["B"] = "Boron"
elements["C"] = "Carbon"
elements["N"] = "Nitrogen"
elements["O"] = "Oxygen"
elements["F"] = "Fluorine"
elements["Ne"] = "Neon"
fmt.Println(elements["Li"])
fmt.Println(elements)
// add if
name, ok := elements["Li"]
fmt.Println(name, ok)
// Map in Map
people := map[string]map[string]string{
"H": map[string]string{
"name": "Hydrogen",
"state": "gas",
},
"He": map[string]string{
"name": "Helium",
"state": "gas",
},
"Li": map[string]string{
"name": "Lithium",
"state": "solid",
},
"Be": map[string]string{
"name": "Beryllium",
"state": "solid",
},
"B": map[string]string{
"name": "Boron",
"state": "solid",
},
"C": map[string]string{
"name": "Carbon",
"state": "solid",
},
"N": map[string]string{
"name": "Nitrogen",
"state": "gas",
},
"O": map[string]string{
"name": "Oxygen",
"state": "gas",
},
"F": map[string]string{
"name": "Fluorine",
"state": "gas",
},
"Ne": map[string]string{
"name": "Neon",
"state": "gas",
},
}
if el, ok := people["Li"]; ok {
fmt.Println(el["name"], el["state"])
fmt.Println(el)
Normal
func average(scores []float64) (float64) {
total := 0.0
for _, value := range scores {
total += value
}
return total / float64(len(scores))
}
多個input參數
func add(arguments ...int) int {
total := 0
for _, value := range arguments {
total += value
}
return total
}
Generator
func makeEvenGenerator() func() uint {
i := uint(0)
fmt.Println("this only be called once")
return func() (ret uint) {
ret = i
i += 2
return
}
}
遞迴
func factorial(x uint) uint {
if x == 0 {
return 1
}
return x * factorial(x-1)
}
defer
func first() {
fmt.Println("first")
}
func second() {
fmt.Println("second")
}
func main() {
defer first()
second()
}
//output:
//second
//first
傳參數
func zero(x int) {
x = 0
}
func main() {
x := 5
zero(x)
fmt.Println(x) // x is still 5
}
傳參考
func zeroByRef(xPtr *int) {
*xPtr = 0
}
func main() {
x := 5
zeroByRef(&x)
fmt.Println(x) // x change to 0
}
傳指標變數
func two(xPtr *int) {
*xPtr = 2
}
func main() {
xPtr := new(int)
two(xPtr)
fmt.Println(*xPtr) //xPtr is 2
}
交換變數的例子
func swap(x *int, y *int) {
zPtr := new(int)
*zPtr = *x
*x = *y
*y = *zPtr
}
func main() {
var (
a = 2
b = 1
)
swap(&a, &b)
fmt.Println("a =", a, "b =", b)
}
Go千萬不要這樣實作
Go的變數參考可以略過那個tmp
func main() {
var (
a = 2
b = 1
)
a, b = b, a
fmt.Println("a =", a, "b =", b)
}
Goroutine
func f(n int) {
for i := 0; i < 10; i++ {
fmt.Println(n, ":", i)
amt := time.Duration(rand.Intn(250))
time.Sleep(time.Millisecond * amt)
}
}
func main() {
for i := 0; i < 10; i++ {
go f(i)
}
var input string
fmt.Scanln(&input)
}
Goroutine IPC with channel
func tim(tim chan<- string) { // 傳入channal 然後一直將 "tim" send進去 tim這個channal
for i := 1; ; i++ { // go's while ( true ) in C lang
tim <- "tim"
}
}
func randy(randy chan<- string) { //可以將傳入方向放在argument宣告 方便讀懂code 如果是雙向都要的時候就不指定方向
for i := 0; ; i++ {
randy <- "randy"
}
}
func receiveChannalAndPrint(leo <-chan string) { // 傳入 channal 然後每秒接收channal的內容
for { // another go's while ( true ) in C lang
msg := <-leo
fmt.Println(msg)
time.Sleep(time.Second * 1)
}
}
func main() {
var c chan string = make(chan string)
go tim(c) //相當於發起thread
go randy(c)
go receiveChannalAndPrint(c)
var input string
fmt.Scanln(&input) //故意讓主程式停住
}
Goroutine with Bufferd channel
chan1 := make(chan string, 10)
chan2 := make(chan string, 10)
go func() {
for {
chan1 <- "from tim"
time.Sleep(time.Second * 1)
}
}() //很像Javascript吧XD
go func() {
for {
chan2 <- "from randy"
time.Sleep(time.Second * 1)
}
}()
go func() {
for {
select {
case msg1 := <-chan1:
fmt.Println("message 1", msg1)
case msg2 := <-chan2:
fmt.Println("message 2", msg2)
case <-time.After(time.Second):
fmt.Println("timeout")
default:
fmt.Println("nothing")
time.Sleep(time.Second * 1)
}
}
}()
使用自定義/內建/第三方函式庫
使用自己的要注意目錄結構(除非你另外放在github上import)
package math
package math
// Finds the average of a series of numbers
func Average(xs []float64) float64 {
total := float64(0)
for _, x := range xs {
total += x
}
return total / float64(len(xs))
}
package main
package main
import (
"./math"
"fmt"
)
func main() {
xs := []float64{1, 2, 3, 4}
avg := math.Average(xs)
fmt.Println(avg)
}
沒有繼承問題
沒有侵入式接口問題
沒有非同步無法測試的問題(Javascript有實做一些方式幫助你處理)
方式你可能覺得跟Javascript超像
沒錯!! 因為它帶了Javascript的優良部份過來
說實在我沒有很喜歡XD
因為不太直觀
average.go
package math
// Finds the average of a series of numbers
func Average(xs []float64) float64 {
total := float64(0)
for _, x := range xs {
total += x
}
return total / float64(len(xs))
}
average_test.go
package math
import "testing"
type testpair struct {
values []float64
average float64
}
var tests = []testpair{
{[]float64{1, 2}, 1.5},
{[]float64{1, 1, 1, 1, 1, 1}, 1},
{[]float64{-1, 1}, 0},
}
func TestAverage(t *testing.T) {
for _, pair := range tests {
v := Average(pair.values)
if v != pair.average {
t.Error(
"For", pair.values,
"expected", pair.average,
"got", v,
)
}
}
}
跳坑玩家提供
https://github.com/stretchr/testifyadd.go
package math
// Finds the sum of a series of numbers
func Add(xs []float64) float64 {
total := float64(0)
for _, x := range xs {
total += x
}
return total
}
add_test.go
package math
import (
"github.com/stretchr/testify/assert"
"testing"
)
type addtestpair struct {
values []float64
sum float64
}
var addtests = []addtestpair{
{[]float64{1, 2}, 3},
{[]float64{1, 1, 1, 1, 1, 1}, 6},
{[]float64{-1, 1}, 0},
{[]float64{1.1, 2.3}, 3.4},
}
func TestAdd(t *testing.T) {
for _, pair := range addtests {
v := Add(pair.values)
assert.Equal(t, v, pair.sum, "they should be equal")
}
}
就照著Google提供的規範走吧
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(
// true
strings.Contains("test", "es"),
// 2
strings.Count("test", "t"),
// true
strings.HasPrefix("test", "te"),
// true
strings.HasSuffix("test", "st"),
// 1
strings.Index("test", "e"),
// "a-b"
strings.Join([]string{"a", "b"}, "-"),
// == "aaaaa"
strings.Repeat("a", 5),
// "bbaa"
strings.Replace("aaaa", "a", "b", 2),
// []string{"a","b","c","d","e"}
strings.Split("a-b-c-d-e", "-"),
// "test"
strings.ToLower("TEST"),
// "TEST"
strings.ToUpper("test"),
)
}