簡潔的語法
雖然看了很多批判go語法的文章榜聂,但是荤懂,我個人還是很喜歡go的風格的燎潮,產品的功能應該做到少即使多蔑滓,就像喬布斯把手機上的按鍵縮減到一個
下面就簡單介紹幾個我比較喜歡的點
多返回值與返回值命名
- 錯誤處理
//傳統(tǒng)的異常處理
try{
var data = fs.readFile();
}catch(e){
print("文件讀取錯誤")
}
//利用多返回值
data,err := fs.readFile()
if(err){
print("文件讀取錯誤")
}
- 命名返回值
func readFull(r io.Reader, buf []byte) (int, error) {
var n int
var err error
for len(buf) > 0 {
var nr int
nr, err = r.Read(buf)
n += nr
if err != nil {
return n, err
}
buf = buf[nr:]
}
return n, err
}
func readFullV2(r io.Reader, buf []byte) (n int, err error) {
for len(buf) > 0 && err == nil {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[nr:]
}
return // 在返回值列表中對變量聲明灰嫉,則可以不必再return語句中寫死
}
break到你想要的地方
TARGET:
for j := 0; j < 5; j++ {
for i := 0; i < 10; i++ {
if i > 5 {
break TARGET
}
fmt.Println(i)
}
}
輸出結果:
0
1
2
3
4
5
平行賦值
- for循環(huán)的時候使用
//平行賦值版本拆宛,go認為平行賦值比較簡潔,所以在for的時候強制使用這種方式
for i, j := 1, 2; i < 10; i, j = i+1, j+1 {
fmt.Println(i, j)
}
//非平行賦值版本
for(i =0,j=1;i<10;i=i+1,j=j+1){
console.log(i,j)
}
- if 的時候使用
//從map中獲取key對應的value
myMap := make(map[string]string)
if value, ok := myMap["aaa"]; ok {
fmt.Println(value)
} else {
fmt.Println("not find")
}
- 交換兩個變量的值
i,j = j,i
數(shù)組的值傳遞
記得面試的時候經常有人會問讼撒,某某語言是引用傳遞還是值傳遞浑厚。這個時候,你就要具體問題決堤分析根盒,告訴他xx類型是引用的钳幅,xx類型是值傳遞
而在Go中,沒有具體問題具體分析這么一說炎滞,全都是值傳遞敢艰,為了充分體現(xiàn)這一驚人,我們以數(shù)組為例子
func demoArray(eles [5]int) {
eles[0] = -1
}
func main() {
data := [5]int{1, 2, 3, 4, 5}
demoArray(data)
fmt.Println(data)//demoArray中的修改對data并不起作用
}
//輸出
[1 2 3 4 5]
defer關鍵字
package main
import (
"fmt"
"os"
)
func main() {
f := createFile("/tmp/defer.txt")
defer closeFile(f)
writeFile(f)
}
func createFile(p string) *os.File {
fmt.Println("creating")
f, err := os.Create(p)
if err != nil {
panic(err)
}
return f
}
func writeFile(f *os.File) {
fmt.Println("writing")
fmt.Fprintln(f, "data")
}
func closeFile(f *os.File) {
fmt.Println("closing")
f.Close()
}
//輸出
creating
writing
closing
- defer關鍵字册赛,主要作用是清理資源钠导,替代了原先的try...catch...finally
- defer 關鍵字后面的表達式,會在函數(shù)return之后執(zhí)行
- 一個函數(shù)中可以有多個defer關鍵字森瘪,按照先進后出的順序執(zhí)行
func a() {
i := 0
defer fmt.Println(i)
i++
return
}
- defer 表達式的變量在定義的時候就已經確定了牡属,所以上面的輸出為0
func c() (i int) {
defer func() { i++ }()
return 1
}
- defer表達式中可以修改函數(shù)中的命名返回值,雖然return的時候為1扼睬,但是調用方獲得的結果為2
友好的大兵團作戰(zhàn)工具
godoc
godoc可以將你本地的go package展示出來逮栅,如下所示:
//Package docDemo is a package using demonstrate godoc tool
package docDemo
import "io"
// ReadFullV2 is a demo of name return value
func ReadFullV2(r io.Reader, buf []byte) (n int, err error) {
for len(buf) > 0 && err == nil {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[nr:]
}
return
}
cgo
package main
/*
#include <stdio.h>
void hello(){
printf("Hello,Cgo\n");
}
*/
import "C"
func main() {
C.hello()
}
上面的小demo展示了,使用C語言打印一個hello
- 在go文件中import "C"表示這是一個帶有Cgo代碼的Go文件
- import前的注釋可以寫你想嵌入的c代碼
- go安裝的時候窗宇,會自帶一個cgo命令行工具措伐,他用來處理所有帶Cgo代碼的Go文件
- 而go 語言的編輯器對于cgo進行了集成,因此担映,直接使用go build就可以完成便利
- 這里只是一個簡單的小例子废士,后面還會在這個話題上深入討論