發表文章

目前顯示的是 8月, 2018的文章

[Redis] [Go] Send 不加 MULTI 會怎麼樣

圖片
做redis transaction 基本上先放MULTI,再SEND要操作的行為後,最後送出EXEC。 但SEND 本身是在做queue的動作,即使沒有先送MULTI,也是可以成功把做queue的指令丟給redis。 為了弄清楚差異,做了一點實驗,以下搭配GOlang。 實驗一: 說明:         將最後的EXEC註解掉,中間插個DO。 結果:         結果DO以前有寫入redis,DO以後的沒作用。 實驗二: 說明:         根據實驗一的基礎上,但最一開始有用MULTI包起來。 結果:         結果即使中間有DO,但都沒寫入redis(DO也沒寫入?)。 實驗三: 說明:         將實驗二最下面的EXEC註解打開。 結果:         通通寫入redis。 結論:                 如果沒包MULTI,會因為有DO的指令,沒而被一起執行下去。         如果有包MULTI,因為MULTI會認EXEC,而導致中間的DO,被吃掉。         碰到EXEC,不管之前有包幾個MULTI,都會一併執行。 Created Date : 2018/08/16 Last Updated Date : 2018/08/16

[Go] Golang 的 slice 進階know how

之前聽別人分享使用slice 遇到有些坑,但未說明來由。 最近在閱讀 Golang 新手可能会踩的 50 个坑 ( 英文原文 ) 也看到關於slice說明的一些現象,為什麼有些值會無故消失,或者無故被更改,於是好奇花了些時間研究了一下。 下列說明配合source code,這邊就不重複貼了。 my source code on github 先說結論,slice的使用方式是pointer。 slice、map、channel 三者在Golang使用上是操作方式是pointer,不熟悉的話建議先把內容copy起來再操作比較保險。 請參考GO FAQ Why are maps, slices, and channels references while arrays are values? 我自己在寫FAQ的心得文章 有印象。 當下是以為在傳遞function的參數,和接受參數的部分對於 maps, slices, and channels 有這樣的說明,不過現在看來這個也是在講平常assign的使用上。 實驗分為test1() test2() test3()。 test1() 和test2() 把某個slice assign到另外一新的變數,表面上看似有了兩個slice,不過是多了一個新的變數名稱,其實指到相同的slice內容而已。 如果改了其中的內容,兩個slice都會影響到,因為他們是指向同樣的地方。 但若(舊的slice + 新的value) ----> 就會自動產生出新的slice,於是跟舊的slice沒有關係了,各改各的不會受影響。 test3() 將記憶體位置印出來,事實上實驗起來,可以發現每個slice裡面的index皆占了一個記憶體空間,假設有兩個slice,裡面的元素可以指向同樣的地方,也可以分別指到不同的地方 x := append(s, 11) // 只有擴到x,但s還是舊的 fmt.Println("cap(s) =", cap(s), "ptr(s) =", &s[0], "ptr(x) =", &x[0]) fmt.Println("cap(s)

[Go] 閱讀心得 不負責任翻譯 Golang Frequently Asked Questions (FAQ) PART4 END

https://golang.org/doc/faq 官方FAQ 提供一些有趣的資訊,很認真的試圖都理解一下,由於內容太多,拆成幾個部分來看。 PART4這裡有 Functions and Methods   Control flow Packages and Testing Implementation  Performance Changes from C --Functions and Methods-- Why do T and *T have different method sets? 接收到型態T的對象,有型態T所有的method,但如果是接收到型態*T,則會擁有型態T和型態*T的所有method。 如果interface裡面包含*T,那麼操作的行為會是pointer,如果是T,那操作的行為只能是value的處理方式。 如果是傳value,copy值之後,就跟原本被copy的部分沒關係了。 What happens with closures running as goroutines? func main() { done := make(chan bool) values := []string{"a", "b", "c"} for _, v := range values { go func() { fmt.Println(v) done <- true }() } // wait for all goroutines to complete before exiting for _ = range values { <-done } } 這個範例是在學GO蠻經典的例子,結論是永遠不要在gorutine裡面直接使用外面的變數。 因為goruntine宣告後並不是馬上建立的,可能等一下才建立,以及複數個gorutine建立起來可能沒有順序性,此時外面的變數已經不知道跑到哪裡去了。 有兩個比較直觀的解法,一個是每次都直接將變數傳入goruntine的function

[Go] 閱讀心得 不負責任翻譯 Golang Frequently Asked Questions (FAQ) PART3

https://golang.org/doc/faq 官方FAQ 提供一些有趣的資訊,很認真的試圖都理解一下,由於內容太多,拆成幾個部分來看。 PART3這裡有 Values   Writing Code   Pointers and Allocation   Concurrency --Values-- Why does Go not provide implicit numeric conversions? 要考量的問題很多,轉換後是否為正數?值會多大?會不會溢位?是否可用? 自動轉換數字型態所帶來的混亂大過好處,沒有特別設計的compile架構很難滿足這個機制。 對GO而言即使64-bit的系統,int也不等於int64的型態。 Why are maps built in? 如strings一樣重要,這種結構可以滿足廣大的定義需求。 map結構,雖然語意寫法稍微不方便了點,但complie的速度快,這應該是可被接受的合理平衡點。 Why don’t maps allow slices as keys? map 裡面的查找,需要equality 運算子(我不清楚這個equality是什麼)。 對於slice是沒有equality 運算子的,但array,和struct有,所以可以當作map的keys。(我的天呀) (會問這種問題,真是超乎想像) Why are maps, slices, and channels references while arrays are values? 為什麼map, slices, and channels 是參考,arrays 是數值。 我的理解是在講call by references 的 references,還有 call by value的value。 map, slices, and channels 是指標,所以不可能生出非指標型態的實體,GO也掙扎的想把array做成這樣。 但會有一些很複雜的作用,所以GO放棄,還是維持value的可用性較高。(這部分看得不是很懂)  -- Writing Code--   How are libraries documented? godoc 提供的功能豐富,可以滿足

[Go] Golang了解 array 和 slice 的差異,簡單說明

array 一開始就宣告大小,不可以再變動。 slice 則是動態增長。 對於array的型態來說,[2]int 和 [3]int 會是不同的型態,長度大小可以理解為某種附加型態,要有指定大小+中括號才是array。 array和slice在執行速度上也差異很多,在我macbook pro 2017,的簡單測試1到100階乘的加總,一個是nanoseconde的運算時間,一個是microsecond。 Created Date : 2018/08/07 Last Updated Date : 2018/08/07

[Go] Golang用法 function input & output 參數可以同樣型態放一起

參數太長該怎麼辦,同樣類型的可以寫在一起。 這件事情我知道的時候還蠻訝異的,同時,又得知不只傳入的參數可以這樣,return的型態也可以這樣搞。 另外,若事先指定回傳的變數名稱,可以在function當中各處先assign你要的回傳值到這些變數。 Input的參數可以類型寫一起 func GetMyData(name string, sex string, birthday string,id int, number int) { } // 可以改寫為 func GetMyData(name, sex, birthday string, id, number int) { } return的參數也可以類型寫一起,並且偷偷宣告變數名稱 func GetMyData(name, sex, birthday string, id, number int) (bool,bool){ } // 可以指定命名 func GetMyData(name, sex, birthday string, id, number int) (isOK bool, isPassed bool){ } // 當然也可以匯集 func GetMyData(name, sex, birthday string, id, number int) (isOK, isPassed bool){ } function 中串插要回傳的值 func GetMyData(name, sex, birthday string, id, number int) (bool, bool){ isOK := true isPassed := false return isOK, isPassed } // 就可以改寫為 func GetMyData(name, sex, birthday string, id, number int) (isOK, isPassed bool){ isOK = true // 中間有些co

[Go] Golang用法 package import 前面的底線

package import 前面的底線 init() 是GO 的關鍵字,每個package都存在一個這樣預設的init() 對於main package來說,在進入main()之前,會先執行init(),如果你有寫在這個package某處的話。 在import package時 對於引用package來講,只會執行這個package的init(),其他部分不會用到。 如使用gorm,我只想用mysql的部分,因此按照文件,我要import “github.com/go-sql-driver/mysql”,但前面加上_ 即可 import ( _ "github.com/go-sql-driver/mysql" "github.com/jinzhu/gorm" ) Created Date : 2018/08/03 Last Updated Date : 2018/08/03

[Go] 閱讀心得 不負責任翻譯 Golang Frequently Asked Questions (FAQ) PART2

https://golang.org/doc/faq 官方FAQ 提供一些有趣的資訊,很認真的試圖都理解一下,由於內容太多,拆成幾個部分來看。 PART2這裡有   Types   Types Is Go an object-oriented language? Go 說是,也不是,有OO的風格,但沒有『繼承』,在GO裡面的interface也跟其他語言的interface有所不同。 透過interface可以達到某些類似subclass的目的,但GO聲明這樣的東西,絕對不等於subclass。 (BOX 和 UBOX 的概念我不清楚,找到的參考是 https://docs.microsoft.com/zh-tw/dotnet/csharp/programming-guide/types/boxing-and-unboxing ,但還是不懂意思,GO表示可以把ubox integer也塞進struct,這很厲害?) 再次聲明,沒有了『繼承』,少了負擔感覺真好。 (OS: 你到底多討厭繼承,這好像我第三次看到了,然後我也覺得就直說不是傳統物件導向的語言,別甲仙啦。) How do I get dynamic dispatch of methods? 『dynamic dispatch of methods』是一個概念,搭配Polymorphism的概念一起看,在GO能做到這件事的唯一方式就是透過interface。 在struct裡面的method和具體的method都是靜態處理。 Why is there no type inheritance? GO想走別的方向,不想要有『繼承』。 沒有『繼承』帶來實質上的好處,『繼承』機制所需要的紀錄彼此關係這件事情,造成很高的複雜度和負擔。 GO的interface可以達到你的目的,再者,沒有了『繼承』就不需要管型態與interface的『明確關係』,每個type可以乾淨的跟interface結合。 (所以其他OO語言,有繼承的type,如果有使用interface,他們之間會定義某種關係狀態,拖累某些處理和速度是嗎?) 舉例fmt.Fprintf 可以印出任何型態的東西,io.Writer可以各種寫入,就是靠『沒繼承』+ 『interface

[Go] 閱讀心得 不負責任翻譯 Golang Frequently Asked Questions (FAQ) PART1

https://golang.org/doc/faq 官方FAQ 提供一些有趣的資訊,很認真的試圖都理解一下,由於內容太多,拆成幾個部分來看。 PART1這裡有  Origins  Usage    Design --Origins-- What is the purpose of the project? 依賴管理對於現在語言非常重要,C語言有著絕佳的速度,但header file的方式在管理依賴這件事上實在非常糟糕。於是想要一個速度快,依賴管理方面又能滿足我們的語言。 沒有『繼承』的概念,這點可以省略『判斷兩個型態彼此之間的關係』所花的時間。(這點蠻有趣的,我不曉得『繼承』需要這樣的cost) Go準備完整的garbage-collected ,來足以應付併發與溝通問題。(以目前所學,各處聽到GO的gb機制多少令人詬病XD) Go是為了多核心機器所設計的語言。(沒錯,這點非常重要!) What is the status of the project? Go 是個開源的poject,有Google撐腰,version 1 是個長期支援的版本。 version 2 改天指日可待! What’s the origin of the mascot? (吉祥物,略) What is the history of the project? (歷史,略) Why are you creating a new language? 這裡說目前主要的程式語言,若達到簡單好上手(直譯式、弱型別)的,那麼就不能滿足安全又快速的條件(我想這是以事先編譯的角度來看)。 Go 想要達到簡單、安全又快速,可以處理併發、多核心的機器。 GO語言目標:在 單一一台機器上,可以快速與有效的執行龐大的程式 。 What are Go’s ancestors? Go 主要血統是C語言,但參雜很多語言的概念,還有新的。 What are the guiding principles in the design? (部份不太懂) 捨棄繼承,type就是純粹的type,而不用聲明type和type的關係(講繼承) 保持概念和原則的純粹,method -->實現任何類型; stru

[Go] 型態轉換 type convert

常用的型態轉換小筆記 int 轉 float64 float64(i) int64 轉 string i := int64(32) str := strconv.FormatInt(i, 10) 參數1 : 要轉的數字 參數2 : 指定進位制,10 >>> 10進位的意思,也可以帶入16 >>> 幫你轉成16進位,再變成字串 string 轉int64 s := "66" i, err := strconv.ParseInt(s, 10, 64) 參數1 : 要轉的字串 參數2 : 指定進位制 參數3 : 位元型態,64 >>> int64,32 >>> int32,8 >>> int8 string 轉 float64 i := "10.53" strconv.ParseFloat(i, 64) 參數1 : 要轉的字串 參數2 : 位元型態,64 >>> float64,32 >>> float32 float64 轉 string i := 23.957232 strconv.FormatFloat(i, ‘f’, 4, 64) 參數1 : 要轉的字串 參數2 : ‘b’ >>> 二進位表示 ’e’ >>> 指數表示(科學符號) ‘E’ >>> 同’e’ ‘f’ >>> 不使用科學符號 ’g’ >>> 大指數表示(我不知道這啥) ‘G’ >>> 同’g’ 參數3 : 小數點後幾位 參數4 : bit-size,原本是float32帶32,float64,帶64 [100]byte 轉string s := string(byteArray[:]) []byte 轉string s := string(byteArray) 有趣的點是byte array 是無法直接轉成string,必須先轉成slice再到string,所以若原本是byte