1. 程式人生 > >Go內部培訓——節點解析1-10

Go內部培訓——節點解析1-10

1. Go 狀態協程

  • 基於通道的方法和Go的通過訊息共享記憶體,保證每份資料為單獨的協程所有的理念是一致的。
package main
import (
"fmt"
"math/rand"
"sync/atomic"
"time"
)
// 在這個例子中,將有一個單獨的協程擁有這個狀態。這樣可以
// 保證這個資料不會被並行訪問所破壞。為了讀寫這個狀態,其
// 他的協程將向這個協程傳送資訊並且相應地接受返回資訊。
// 這些`readOp`和`writeOp`結構體封裝了這些請求和回覆
type readOp struct {
key int
resp chan int
}
type
writeOp struct { key int val int resp chan bool } func main() { // 我們將計算我們執行了多少次操作 var ops int64 = 0 // reads和writes通道將被其他協程用來從中讀取或寫入資料 reads := make(chan *readOp) writes := make(chan *writeOp) // 這個是擁有`state`的協程,`state`是一個協程的私有map // 變數。這個協程不斷地`select`通道`reads`和`writes`, // 當有請求來臨的時候進行回覆。一旦有請求,首先執行所 // 請求的操作,然後給`resp`通道傳送一個表示請求成功的值。
go func() { go func() { var state = make(map[int]int) for { select { case read := <-reads: read.resp <- state[read.key] case write := <-writes: state[write.key] = write.val write.resp <- true } } }() // 這裡啟動了100個協程來向擁有狀態的協程請求讀資料。 // 每次讀操作都需要建立一個`readOp`,然後傳送到`reads` // 通道,然後等待接收請求回覆 for r := 0
; r < 100; r++ { go func() { for { read := &readOp{ key: rand.Intn(5), resp: make(chan int)} reads <- read <-read.resp atomic.AddInt64(&ops, 1) } }() } // 我們開啟10個寫協程 for w := 0; w < 10; w++ { go func() { for { write := &writeOp{ key: rand.Intn(5), val: rand.Intn(100), resp: make(chan bool)} writes <- write <-write.resp atomic.AddInt64(&ops, 1) } }() } // 讓協程執行1秒鐘 time.Sleep(time.Second) // 最後輸出運算元量ops的值 opsFinal := atomic.LoadInt64(&ops) fmt.Println("ops:", opsFinal) }

2. Go字典

  • 字典是Go語言內建的關聯資料型別。因為陣列是索引對應陣列元素,而字典是鍵對應值。
package main
import "fmt"
func main() {
// 建立一個字典可以使用內建函式make
// "make(map[鍵型別]值型別)"
m := make(map[string]int)
// 使用經典的"name[key]=value"來為鍵設定值
m["k1"] = 7
m["k2"] = 13
// 用Println輸出字典,會輸出所有的鍵值對
fmt.Println("map:", m)
// 獲取一個鍵的值 "name[key]".
v1 := m["k1"]
fmt.Println("v1: ", v1)
// 內建函式返回字典的元素個數
fmt.Println("len:", len(m))
// 內建函式delete從字典刪除一個鍵對應的值
delete(m, "k2")
fmt.Println("map:", m)
// 根據鍵來獲取值有一個可選的返回值,這個返回值表示字典中是否
// 存在該鍵,如果存在為true,返回對應值,否則為false,返回零值
// 有的時候需要根據這個返回值來區分返回結果到底是存在的值還是零值
// 比如字典不存在鍵x對應的整型值,返回零值就是0,但是恰好字典中有
// 鍵y對應的值為0,這個時候需要那個可選返回值來判斷是否零值。
_, ok := m["k2"]
fmt.Println("ok:", ok)
// 你可以用 ":=" 同時定義和初始化一個字典
n := map[string]int{"foo": 1, "bar": 2}
fmt.Println("map:", n)
}

3. Go 字串操作函式

  • strings 標準庫提供了很多字串操作相關的函式。這裡提供的幾個例子是讓你先對這個包有個基本瞭解。
package main
import s "strings"
import "fmt"
// 這裡給fmt.Println起個別名,因為下面我們會多處使用。
var p = fmt.Println
func main() {
// 下面是strings包裡面提供的一些函式例項。注意這裡的函式並不是
// string物件所擁有的方法,這就是說使用這些字串操作函式的時候
// 你必須將字串物件作為第一個引數傳遞進去。
p("Contains: ", s.Contains("test", "es"))
p("Count: ", s.Count("test", "t"))
p("HasPrefix: ", s.HasPrefix("test", "te"))
p("HasSuffix: ", s.HasSuffix("test", "st"))
p("Index: ", s.Index("test", "e"))
p("Join: ", s.Join([]string{"a", "b"}, "-"))
p("Repeat: ", s.Repeat("a", 5))
p("Replace: ", s.Replace("foo", "o", "0", -1))
p("Replace: ", s.Replace("foo", "o", "0", 1))
p("Split: ", s.Split("a-b-c-d-e", "-"))
p("ToLower: ", s.ToLower("TEST"))
p("ToUpper: ", s.ToUpper("test"))
p()
// 你可以在strings包裡面找到更多的函式
// 這裡還有兩個字串操作方法,它們雖然不是strings包裡面的函式,
// 但是還是值得提一下。一個是獲取字串長度,另外一個是從字串中
// 獲取指定索引的字元
p("Len: ", len("hello"))
p("Char:", "hello"[1])
}

4. Go 字串格式化

  • Go對字串格式化提供了良好的支援。下面我們看些常用的字串格式化的例子。
package main
import "fmt"
import "os"
type point struct {
x, y int
}
func main() {
// Go提供了幾種列印格式,用來格式化一般的Go值,例如
// 下面的%v列印了一個point結構體的物件的值
p := point{1, 2}
fmt.Printf("%v\n", p)
// 如果所格式化的值是一個結構體物件,那麼`%+v`的格式化輸出
// 將包括結構體的成員名稱和值
fmt.Printf("%+v\n", p)
// `%#v`格式化輸出將輸出一個值的Go語法表示方式。
fmt.Printf("%#v\n", p)
// 使用`%T`來輸出一個值的資料型別
fmt.Printf("%T\n", p)
// 格式化布林型變數
fmt.Printf("%t\n", true)
// 有很多的方式可以格式化整型,使用`%d`是一種
// 標準的以10進位制來輸出整型的方式
fmt.Printf("%d\n", 123)
// 這種方式輸出整型的二進位制表示方式
fmt.Printf("%b\n", 14)
// 這裡打印出該整型數值所對應的字元
fmt.Printf("%c\n", 33)
// 使用`%x`輸出一個值的16進製表示方式
fmt.Printf("%x\n", 456)
// 浮點型數值也有幾種格式化方法。最基本的一種是`%f`
fmt.Printf("%f\n", 78.9)
// `%e`和`%E`使用科學計數法來輸出整型
fmt.Printf("%e\n", 123400000.0)
fmt.Printf("%E\n", 123400000.0)
// 使用`%s`輸出基本的字串
fmt.Printf("%s\n", "\"string\"")
// 輸出像Go原始碼中那樣帶雙引號的字串,需使用`%q`
fmt.Printf("%q\n", "\"string\"")
// `%x`以16進位制輸出字串,每個字串的位元組用兩個字元輸出
fmt.Printf("%x\n", "hex this")
// 使用`%p`輸出一個指標的值
fmt.Printf("%p\n", &p)
// 當輸出數字的時候,經常需要去控制輸出的寬度和精度。
// 可以使用一個位於%後面的數字來控制輸出的寬度,預設
// 情況下輸出是右對齊的,左邊加上空格
fmt.Printf("|%6d|%6d|\n", 12, 345)
// 你也可以指定浮點數的輸出寬度,同時你還可以指定浮點數
// 的輸出精度
fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)
// To left-justify, use the `-` flag.
fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)
// 你也可以指定輸出字串的寬度來保證它們輸出對齊。預設
// 情況下,輸出是右對齊的
fmt.Printf("|%6s|%6s|\n", "foo", "b")
// 為了使用左對齊你可以在寬度之前加上`-`號
fmt.Printf("|%-6s|%-6s|\n", "foo", "b")
// `Printf`函式的輸出是輸出到命令列`os.Stdout`的,你
// 可以用`Sprintf`來將格式化後的字串賦值給一個變數
s := fmt.Sprintf("a %s", "string")
fmt.Println(s)
// 你也可以使用`Fprintf`來將格式化後的值輸出到`io.Writers`
fmt.Fprintf(os.Stderr, "an %s\n", "error")
}

5. Go 自定義排序

  • 有的時候我們希望排序不是僅僅按照自然順序排序。例如,我們希望按照字串的長度來對一個字串陣列排序而不是按照字母順序來排序。這裡我們介紹一下Go的自定義排序。
package main
import "sort"
import "fmt"
// 為了能夠使用自定義函式來排序,我們需要一個
// 對應的排序型別,比如這裡我們為內建的字串
// 陣列定義了一個別名ByLength
type ByLength []string
// 我們實現了sort介面的Len,Less和Swap方法
// 這樣我們就可以使用sort包的通用方法Sort
// Len和Swap方法的實現在不同的型別之間大致
// 都是相同的,只有Less方法包含了自定義的排序
// 邏輯,這裡我們希望以字串長度升序排序
func (s ByLength) Len() int {
return len(s)
}
func (s ByLength) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByLength) Less(i, j int) bool {
return len(s[i]) < len(s[j])
}
// 一切就緒之後,我們就可以把需要進行自定義排序
// 的字串型別fruits轉換為ByLength型別,然後使用
// sort包的Sort方法來排序
func main() {
fruits := []string{"peach", "banana", "kiwi"}
sort.Sort(ByLength(fruits))
fmt.Println(fruits)
}

6. Go Base64編碼

  • Go提供了對base64編碼和解碼的內建支援。
package main
// 這種匯入包的語法將預設的base64起了一個別名b64,這樣
// 我們在下面就可以直接使用b64表示這個包,省點輸入量
import b64 "encoding/base64"
import "fmt"
func main() {
// 這裡是我們用來演示編碼和解碼的字串
data := "abc123!?$*&()'[email protected]~"
// Go支援標準的和相容URL的base64編碼。
// 我們這裡使用標準的base64編碼,這個
// 函式需要一個`[]byte`引數,所以將這
// 個字串轉換為位元組陣列
sEnc := b64.StdEncoding.EncodeToString([]byte(data))
fmt.Println(sEnc)
// 解碼一個base64編碼可能返回一個錯誤,
// 如果你不知道輸入是否是正確的base64
// 編碼,你需要檢測一些解碼錯誤
sDec, _ := b64.StdEncoding.DecodeString(sEnc)
fmt.Println(string(sDec))
fmt.Println()
// 使用相容URL的base64編碼和解碼
uEnc := b64.URLEncoding.EncodeToString([]byte(data))
fmt.Println(uEnc)
uDec, _ := b64.URLEncoding.DecodeString(uEnc)
fmt.Println(string(uDec))
}

7. Go Defer

  • Defer 用來保證一個函式呼叫會在程式執行的最後被呼叫。通常用於資源清理工作。
package main
import "fmt"
import "os"
// 假設我們想建立一個檔案,然後寫入資料,最後關閉檔案
func main() {
// 在使用createFile得到一個檔案物件之後,我們使用defer
// 來呼叫關閉檔案的方法closeFile,這個方法將在main函式
// 最後被執行,也就是writeFile完成之後
f := createFile("/tmp/defer.txt")
// Windows下面使用這個語句
// f := createFile("D:\\Temp\\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()
}

Go Exit
使用 os.Exit 可以給定一個狀態,然後立刻退出程式執行。

package main
import "fmt"
import "os"
func main() {
// 當使用`os.Exit`的時候defer操作不會被執行,
// 所以這裡的``fmt.Println`將不會被呼叫
defer fmt.Println("!")
// 退出程式並設定退出狀態值
os.Exit(3)
}

8. Go for迴圈

  • for迴圈是Go語言唯一的迴圈結構。這裡有三個基本的for迴圈型別。
package main
import "fmt"
func main() {
// 最基本的一種,單一條件迴圈
// 這個可以代替其他語言的while迴圈
i := 1
for i <= 3 {
fmt.Println(i)
i = i + 1
}
// 經典的迴圈條件初始化/條件判斷/迴圈後條件變化
for j := 7; j <= 9; j++ {
fmt.Println(j)
}
// 無條件的for迴圈是死迴圈,除非你使用break跳出迴圈或者
// 使用return從函式返回
for {
fmt.Println("loop")
break
}
}

9. Go if…else if…else 條件判斷

package main
import "fmt"
func main() {
// 基本的例子
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
// 只有if條件的情況
if 8%4 == 0 {
fmt.Println("8 is divisible by 4")
}
// if條件可以包含一個初始化表示式,這個表示式中的變數
// 是這個條件判斷結構的區域性變數
if num := 9; num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
}

10. Go JSON支援

  • Go內建了對JSON資料的編碼和解碼,這些資料的型別包括內建資料型別和自定義資料型別。
package main
import "encoding/json"
import "fmt"
import "os"
// 我們使用兩個結構體來演示自定義資料型別的JSON資料編碼和解碼。
type Response1 struct {
Page int
Fruits []string
}
type Response2 struct {
Page int `json:"page"`
Fruits []string `json:"fruits"`
}
func main() {
// 首先我們看一下將基礎資料型別編碼為JSON資料
bolB, _ := json.Marshal(true)
fmt.Println(string(bolB))
intB, _ := json.Marshal(1)
fmt.Println(string(intB))
fltB, _ := json.Marshal(2.34)
fmt.Println(string(fltB))
strB, _ := json.Marshal("gopher")
fmt.Println(string(strB))
// 這裡是將切片和字典編碼為JSON陣列或物件
slcD := []string{"apple", "peach", "pear"}
slcB, _ := json.Marshal(slcD)
fmt.Println(string(slcB))
mapD := map[string]int{"apple": 5, "lettuce": 7}
mapB, _ := json.Marshal(mapD)
fmt.Println(string(mapB))
// JSON包可以自動地編碼自定義資料型別。結果將只包括自定義
// 型別中的可匯出成員的值並且預設情況下,這些成員名稱都作
// 為JSON資料的鍵
res1D := &Response1{
Page: 1,
Fruits: []
            
           

相關推薦

Go內部培訓——節點解析1-10

1. Go 狀態協程 基於通道的方法和Go的通過訊息共享記憶體,保證每份資料為單獨的協程所有的理念是一致的。 package main import ( "fmt" "math/rand" "sync/atomic" "time" ) // 在這個例子中,將有一個單獨的

Go內部培訓——節點解析31-40

31. Go 函式定義 函式是Go語言的重要內容。 package main import "fmt" // 這個函式計算兩個int型輸入資料的和,並返回int型的和 func plus(a int, b int) int { // Go需要使用return語句顯式地返

Go內部培訓——節點解析21-30

21. Go 並行通道Channel Channel是連線並行協程(goroutine)的通道。你可以向一個通道寫入資料然後從另外一個通道讀取資料。 package main import "fmt" func main() { // 使用`make(chan 資料型別

Go內部培訓——節點解析11-20

11. Go Line Filters package main import ( "bufio" "fmt" "os" "strings" ) func main() { // 使用緩衝scanner來包裹無緩衝的`os.Stdin`可以讓我們 // 方便地使用`Scan`方法,這個方

Bugku CTF 題目解析 (1-10題)

寫在前面的話:   這裡只是記錄一些自己的解題思路,或者一些有關解題的亂七八糟的東西,自己是剛零基礎接觸這方面的東西,所以有表述不當的地方請包容,在此謝過! 1、web2 點開網址後: 解題思路:F12 開啟 開發者工具看看,可以看到需要尋找的flag。

Go內部培訓——14.常用使用的包整理及介紹

1.Go 標準庫可以大致按其中庫的功能進行以下粗略的分類 輸入輸出。這個分類包括二進位制以及文字格式在螢幕、鍵盤、檔案以及其他裝置上的輸 入輸出等,比如二進位制檔案的讀寫。對應於此分類的包有bufio、 fmt、 io、 log和flag 等,其中 flag 用於處理命令列引

Go內部培訓——13.Go的Goroutine

1. Goroutine 1.1 Go 在語言層面對併發程式設計提供支援,一種類似協程,稱作 goroutine 的機制 怎麼實現go程呢,只需在函式呼叫語句前新增 go 關鍵字,就可建立併發執行單元。開發⼈人員無需瞭解任何執行細節,排程器會自動將其安排到合適的系統執行緒

HyperLedger Fabric 1.2 單機單節點部署(10.2)

point having itl img chm same value lock eat 單機單節點指在一臺電腦上部署一個排序(Orderer)服務、一個組織(Org1),一個節點(Peer,屬於Org1),然後運行官方案例中的example02智能合約例子,

Atitit 常見概念與技術 dom及其解析 目錄 1.1. Dom概念(文件物件模型(Document Object Model))是什麼 1 1.1.1. 節點 2 1.1.2. Node 層次

Atitit 常見概念與技術 dom及其解析   目錄 1.1. Dom概念(文件物件模型(Document Object Model))是什麼 1 1.1.1. 節點 2 1.1.2. Node 層次 2 1.1.3. 文件樹 3 2. Dom分類 3 2

在Ubuntu 16.04.3 LTS上安裝Go 1.10

升級Go新版本的原因目前Ubuntu 16.04.3上最新的二進位制Go版本是1.6.2,執行github上的一個大的go專案,發現context包在go版本1.6以上和以下的import方式有差異在go1.7及以上版本context包被正式列入官方庫中,所以我們只需要imp

Google內部培訓1.8萬人的機器學習速成課

什麼是(監督)機器學習?簡而言之,它是以下幾點: ML系統學習如何組合輸入以產生對從未見過的資料的有用預測。 我們來探討基本的機器學習術語。 標籤 一個 標籤是我們預測物品的屬性, 比如變數y在簡單線性迴歸變數。標籤可以是小麥的未來價格,圖片中顯示的動物的種類,音訊剪輯的

在CentOS 6.9上從原始碼安裝Go 1.10

詳見本博博文http://blog.csdn.net/tao_627/article/details/79375950這裡只是簡單記錄一下實操步驟,假定使用者為root:wget https://dl.google.com/go/go1.10.linux-amd64.tar.

個人珍藏的80道多執行緒併發面試題(1-10答案解析

前言 個人珍藏的80道Java多執行緒/併發經典面試題,因為篇幅太長,現在先給出1-10的答案解析哈,後面一起完善,並且上傳github哈~ ❝ https://github.com/whx123/JavaHome ❞ 「公眾號:撿田螺的小男孩」 1. synchronized的實現原理以及鎖優化? sync

【extjs6學習筆記】1.10 初始: 定義類

ria nbsp src clas -1 學習 ref 定義類 mage http://www.extjs-tutorial.com/extjs/define-new-class-in-extj

centos nginx-1.10.3 安裝

依賴 centos .org fix download 配置 表達式 amp zxvf wget http://nginx.org/download/nginx-1.13.1.tar.gz nginx 依賴 pcre 庫,要先安裝pcre,因為nginx 要在rewrite

Cts框架解析(1)-windows下cts配置

javac 啟動 snippet htm html stc host ech 技術分享 環境搭建 下載 cts工具的下載地址:http://source.android.com/compatibility/downloads.html

NOI-1.1-10-字符表示超級瑪麗

nbsp urn algorithm namespace blog using 字符 names ret 10:超級瑪麗遊戲 總時間限制: 1000ms 內存限制: 65536kB描述 超級瑪麗是一個非常經典的遊戲。請你用字符畫的形式輸出超級瑪麗中的一個場景。 輸入

[51nod] 1087 1 10 100 1000

true ret namespace sof nbsp class 類型 color nod 1,10,100,1000...組成序列1101001000...,求這個序列的第N位是0還是1。 Input 第1行:一個數T,表示後面用作輸入測試的數的數量。(1

PAT (Basic Level) Practise水題1~10

call ++ 真的 evel -a namespace cal 多少 all 1001. 害死人不償命的(3n+1)猜想 (15) 卡拉茲(Callatz)猜想: 對任何一個自然數n,如果它是偶數,那麽把它砍掉一半;如果它是奇數,那麽把(3n+1)砍掉一半。這樣一直反復砍

File Inclusion 代碼解析 1

require != 本地文件 簡單 刪除 配置文件 block 失敗 ado File Inclusion,意思是文件包含(漏洞),是指當服務器開啟allow_url_include選項時,就可以通過php的某些特性函數(include(),require()和inclu