Java 轉 Go 之初體驗
面試了一個單位 說可能需要java轉go語言 所以在此開始學習一下 如果面試通過了就繼續學 沒面試過 那么就這一篇了 加油!!!
# 萬能之Hello World 開啟go的大門
直接上代碼
package main //表明包
import "fmt" //導入包 fmt 控制輸入輸出 感覺和java的System.out和Scanner有點像
func main() {
fmt.Println("Hello Go world。"); //進入這個世界了
}
輸出結果:

是不是感覺還可以。
# Go語言環境安裝
安裝包下載地址為:https://golang.org/dl/。
如果打不開可以使用這個地址:https://golang.google.cn/dl/。

我安裝的是windows版的 雙擊安裝選擇目錄 全程輕松隨意 比想象中簡單

配置系統變量,然后就可以開始玩了

# 基礎語法
- 行分割符:不需要像java一眼每句之后都加一個;表明結束 每一行都是單獨的一句 如果非要把幾行語句寫在一起 就需要加分號了
- 注釋 : //單行注釋
/*
aaa
bbb
*/
- 標識符 標識符用來命名變量、類型等程序實體。一個標識符實際上就是一個或是多個字母(AZ和az)數字(0~9)、下劃線_組成的序列,但是第一個字符必須是字母或下劃線而不能是數字。
- 字符串連接 直接用+號即可連接 這點倒是和java挺像的 但是java里直接用加號連接的性能不是很好 不知道go語言中是否有相類似的編譯流程
- 關鍵字

- 預定義標識符

# 數據類型

數據類型詳細的可以看這個:https://www.runoob.com/go/go-data-types.html
首先一點,給我印象比較深的就是 對數字類型添加了很多的包裝,在不同的應用范圍內使用不同的數據類型 例如
- int8 有符號 8 位整型 (-128 到 127)
- int16 有符號 16 位整型 (-32768 到 32767)
- int32 有符號 32 位整型 (-2147483648 到 2147483647)
- int64 有符號 64 位整型 (-9223372036854775808 到 9223372036854775807)
這個給人感覺就是對使用著感覺 有了更高的要求 像java就是int Integer BigInteger這幾種包裝好的用就行了
當然這樣要求的更細致 感覺編譯的時候 就越容易控制 如果方方面面都這么細致的話 運行速度上就可以提高不少的
# 聲明變量
- var identifier type 例:var a int;
- var identifier1,identifier2 type 例:var a,b string;
- 指定變量類型,如果沒有初始化,則變量默認為零值
數值類型(包括complex64/128)為 0
布爾類型為 false
字符串為 “”(空字符串)
以下幾種類型為 nil:
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口
- 根據值自行判定變量類型 例:var d = true (這點就有點像js了)
- 省略 var, 注意 := 左側如果沒有聲明新的變量,就產生編譯錯誤,格式:v_name := value 例:f := “Runoob”
- 多變量聲明
//類型相同多個變量, 非全局變量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
// 和 python 很像,不需要顯示聲明類型,自動推斷
var vname1, vname2, vname3 = v1, v2, v3
// 出現在 := 左側的變量不應該是已經被聲明過的,否則會導致編譯錯誤
vname1, vname2, vname3 := v1, v2, v3
// 這種因式分解關鍵字的寫法一般用于聲明全局變量
var (
vname1 v_type1
vname2 v_type2
)
# 常量
const 定義常量關鍵字 目前感覺和final static 類似
定義了之后就不能改了 如果代碼里面改了的話 會報 cannot assign to LENGTH 錯誤

下來就發現一個神奇懂東西 iota
iota,特殊常量,可以認為是一個可以被編譯器修改的常量。
iota 在 const關鍵字出現時將被重置為 0(const 內部的第一行之前),const 中每新增一行常量聲明將使 iota 計數一次(iota 可理解為 const 語句塊中的行索引)。

枚舉自增計數器 感覺是這么個意思
# 運算符




&這個就是只有兩個1的時候才是1其余都是0
|這個是只有兩個0的時候才是0其余都是1和與剛好相反
^這個簡單粗暴兩個相同的數字是0不同的時候是1


這個<<=后面的幾個都還有點驚艷到我了 厲害厲害

這兩個優點沒太看懂 敲個代碼試一下
package main
import "fmt"
func main(){
var a string = "abc"
var ptr *string = &a
fmt.Printf("第 1 行 - a 變量類型為 = %T", a );
fmt.Printf("第 2 行 - ptr 變量類型為 = %T", ptr );
fmt.Println(*ptr)
fmt.Println(ptr)
}

加*輸出的是內容 不加輸出的就是地址 這個指針的概念 java里是沒有的

這一part 感覺除了指針的概念 其余的感覺都差不多
詳細例子:https://www.runoob.com/go/go-constants.html
# 條件語句

這個select語句真的是看的我欲生欲死
以下描述了 select 語句的語法:
每個 case 都必須是一個通信
所有 channel 表達式都會被求值
所有被發送的表達式都會被求值
如果任意某個通信可以進行,它就執行,其他被忽略。
如果有多個 case 都可以運行,Select 會隨機公平地選出一個執行。其他不會執行。
否則:
如果有 default 子句,則執行該語句。
如果沒有 default 子句,select 將阻塞,直到某個通信可以運行;Go 不會重新對 channel 或值進行求值。
來來來 兩段代碼說明一下
package main
import (
"fmt"
)
func fibonacci(c, quit chan int) {
x, y := 1, 1
for {
select {
case c <- x:
fmt.Printf("x : %d, y : %d", x, y)
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
func main() {
c := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 6; i++ {
fmt.Printf("開始搞事 i = %d", i)
fmt.Println(<-c)
}
quit <- 0
}()
fibonacci(c, quit)
}
輸出結果為:

第二段代碼:
package main
import (
"fmt"
"time"
)
func Chann(ch chan int, stopCh chan bool) {
for j := 0; j < 10; j++ {
ch <- j
time.Sleep(time.Second)
}
stopCh <- true
}
func main() {
ch := make(chan int)
c := 0
stopCh := make(chan bool)
go Chann(ch, stopCh)
for {
select {
case c = <-ch:
fmt.Println("Recvice", c)
fmt.Println("channel")
case s := <-ch:
fmt.Println("Receivessss", s)
case _ = <-stopCh:
goto end
}
}
end:
}
輸出結果為:

這兩個例子分別說明了下面兩點
如果任意某個通信可以進行,它就執行,其他被忽略。
如果有多個 case 都可以運行,Select 會隨機公平地選出一個執行。其他不會執行。
但是有個疑問 為啥第一個例子里在執行偶數次的時候 xy會交換兩次 在下一次調用的時候又不會進行交換?內部是怎么實現的???真想打個斷點調試一下 這個問題如果我往后會做go的話 我一定會回來的!!!!