[Golang][程式設計週記].. 2015第四週

##雜七雜八感言:

啊… 我覺得我blog樣板好醜啊….應該要改成Patrick類似的… 本來想加回廣告的… 後來看到每天流量沒有破百…. 算了….

##筆記:

以下是關於本週的學習筆記…

###[Golang] 一些有趣的package 跟 網站

[Golang] “Beego” Framework: An open source framework to build and develop your applications in the Go way

image

[Golang] Concurrency 實戰初體驗-

  • 一開始學習都Go Routine都是寫一些簡單的程式,最近有機會應用到網站上面的時候,有一些簡單的心得.也順便把所有的Godoc仔細地查看了一下.
  • 使用時機:
    • 需要他的回傳值或是修改後的結果,使用Channel
    • 不需要,就直接使用Goroutines
    • goroutines如果有太多參數要使用,直接寫成在func裡面.
  • 使用成效:
    • 一個需要用到對照查詢的部分,原本要40s可以節省到1/3(甚至更少..).
  

// 一個effective_go 上透過channel完成類似message queue的概念
var sem = make(chan int, MaxOutstanding) //MaxOutstanding 最多可執行的thread數

func handle(r *Request) {
    // sem在這邊只是作為MaxOutstanding的個數參考,如果超過MaxOutstanding就無法指定新的數值
    sem <- 1    // Wait for active queue to drain.
    process(r)  // May take a long time.
    <-sem       // Done; enable next request to run.
}

func Serve(queue chan *Request) {
    for {
        //等待新的message(request)進來
        req := <-queue
        go handle(req)  // Don't wait for handle to finish.
    }
}

[RPI+node.js]自己的 Dropcam 自己 Make

  • 有人把自己整套dropcam的solution 包含伺服器與RPI上面client的code都分享出來.並且透過deploy to heroku這個按鈕,可以一鍵部署到heroku去.
  • 完整source code在這裡image

[Cloud Load Testing]關於負載測試的服務與提供

  • 主要是由Azure看到的服務介紹,來瞭解到原來雲端負載測試是可以外包給雲端服務的.不過考量到伺服器的測試會造成許多額外得費用.這部分想玩還要找時機啊.
  • Blitz另外一家雲端負載測試公司
  • Loadstorm 這也是另外一家….

[Other] 雜七雜八的鏈結

[Code Style] Python Google Code Style

[Golang] Enable HTTPS in martini using martini-contrib/secure

image

實在有點懶得用中文來寫了… 讓我用英文寫這篇吧…

Before this..

I am learning about golang on server backend side programming via martini. I want to write a RESTful server communicate via JSON. Currently my framework as follow:

Here is the note about how I add martini-secure HTTPS in martini.

Working step with martini-secure

1. Create a SSL key using generate_cert.go

You need create your localhost SSL key (or purchase one from CA) using generate_cert.go. I am not sure how to get this package, so I just download this source code and run it locally.

go run generate_cert.go --host="localhost"

You will get file “key.pem” and “cert.pem”, just put in your web side source code.

2. Apply martini-secure in martini program.

It is very easy to add SSL as a plugin in martini, here is some code. At first I would like to host two services as follow:

  • HTTP: port 8080
  • HTTPS: port 8443
m := martini.Classic()

// Make sure this enable, or it will get failed.
martini.Env = martini.Prod

    
m.Use(secure.Secure(secure.Options{
	SSLRedirect: false,
	SSLHost:     "localhost:8443",
}))

m.Get("/foo", func() string {
	return "bar"
})

go func() {
	if err := http.ListenAndServe(":8080", m); err != nil {
		fmt.Println(err)
	}
}()

// HTTPS, make sure "cert.pem" and "key.pem" files are exist.
if err := http.ListenAndServeTLS(":8443", "cert.pem", "key.pem", m); err != nil {
	fmt.Println(err)
}

3. Write a client to verity it.

If it build with luck, let’s verify with some simple client code as follow:

  • TLSClientConfig: true : Because we use custom SSL key, not signed by CA.
package main

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

func HttpsVerity(address string) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}

	client := &http.Client{Transport: tr}

	response, err := client.Get(address)
	if err != nil {
		fmt.Printf("%s", err)
		os.Exit(1)
	} else {
		defer response.Body.Close()
		contents, err := ioutil.ReadAll(response.Body)
		if err != nil {
			fmt.Printf("%s", err)
			os.Exit(1)
		}
		fmt.Printf("%s\n", string(contents))
	}
}

func HttpVerity(address string) {
	client := &http.Client{}

	response, err := client.Get(address)
	if err != nil {
		fmt.Printf("%s", err)
		os.Exit(1)
	} else {
		defer response.Body.Close()
		contents, err := ioutil.ReadAll(response.Body)
		if err != nil {
			fmt.Printf("%s", err)
			os.Exit(1)
		}
		fmt.Printf("%s\n", string(contents))
	}
}

func main() {
	fmt.Println("HTTP")
	HttpVerity("http://localhost:8080/foo")
	fmt.Println("HTTPS")
	HttpsVerity("https://localhost:8443/foo")
}

Problems you might occur

tls: oversized record received with length 20527

  • Root cause:
    • Server side SSL configuration failed, might related to key files.
  • Solution:
    • You forget to add “http.ListenAndServeTLS” in your server side also check SSL key files if missing.

Cannot connect original HTTP protocol

  • Root cause:
    • martini-secure default enable SSL redirect, so original HTTP protocol will redirect to HTTPS.
  • Solution:
    • Add following code in your server side.
m.Use(secure.Secure(secure.Options{
	SSLRedirect: false,
}))               	

Show your web side is not secure when using web browser

  • Root cause:
    • We are using custom SSL key which don’t signed by CA. So it will show error when you using browser to browse your server.
  • Solution:
    • Buy a offcial SSL key.

How to deploy HTTPS on heroku using martini

It is very easy to deploy HTTPS on Heroku, using SSL Endpoint. All you need as follow:

  • Enable SSL Endpoint in Heroku ($20/per month)
  • Purchase a valid srt from a legal CA, and apply to Heroku.
  • Assign your domain name to HTTPS host (such as XXXX..herokussl.com)
  • Your application just handle HTTP request as well.
  • And.. That’s done. :)

Hope you can enjoy martini as well.

[Golang][程式設計週記].. 2015第3週.. 20150123

image

前言:

看起來每個禮拜一篇的紀錄會有點繁雜,應該要把所有文章拆開來一篇一篇儲存.但是很多部分沒辦法一次寫完又很痛苦. 再觀察看看要怎麼寫好了.

筆記:

  

// 隱藏AuthToken ,在JSON中完全不會出現.
type SafePerson struct {
    FirstName string
    LastName  string
    AuthToken string `json:"-"`
}

// 如果沒有值,就不會出現在JSON裡面.
type PrettySafePerson struct {
    FirstName string
    LastName  string
    AuthToken string `json:",omitempty"`
}

image

  • [Golang] A GO Pusher server implementation compatible with Pusher client libraries
    • git
    • Pusher Server是一個相當特別的功能,可以透過一個REST API連接到 Pusher Server直接透過web socket 來跟瀏覽器溝通,達到許多前端的功能.
    • 看起來蠻值得研究一下pusher server,不過我對前端的部分真的很不熟啊……
  • [Golang]關於Martini Render HTML template
    • 使用起來其實跟以前用過許多PHP template相同,簡單又好用.
    • template的檔案(*.tmpl)一定要放在 templates\ ,當然也可以透過Render Option來設定.
    • 這裏有影片教學,可以解決大部分的疑問.
  • [Golang] XML encode 研究
    • 主要是針對XML範例,做一個簡單研究.針對value與attribute處理的部份.
    • 參考這裏
  
/*
< ?xml version="1.0" encoding="UTF-8"?>
< Response>
    < Say voice="alice">Thanks for trying our documentation. Enjoy!</Say>
    < Play>http://demo.twilio.com/docs/classic.mp3</Play>
< /Response>
*/


package main

import (
	"encoding/xml"
	"fmt"
	"os"
)

func main() {
	type Say struct {
		Voice string `xml:"voice,attr"`
		Value string `xml:",chardata"`
	}
	type CallResponse struct {
		XMLName xml.Name `xml:"Response"`
		Play    string   `xml:"Play"`
		SayObj  Say      `xml:"Say"`
	}

	v := &CallResponse{Play: "http://demo.twilio.com/docs/classic.mp3"}
	v.SayObj = Say{Voice: "alice", Value: "Thanks for trying our documentation. Enjoy!"}

	enc := xml.NewEncoder(os.Stdout)
	enc.Indent("  ", "    ")
	if err := enc.Encode(v); err != nil {
		fmt.Printf("error: %v\n", err)
	}

}
  • [Windows10] 本週科技上比較大件事就是Win10的一個公開發表
    • 特點:
      1. 免費升級(Win7/Win8.1/WinPhone8.1) (不過叔叔們有練過~Win7升級前請三思…. XD)
      2. Universal App (寫一個app所有 Microsoft phone/平板/PC/X1 都可用 “理想中”)
    • 吐槽點:
      1. 竟然在demo裡面用手指去點那個小到不行的task bar.. 大手指錯了嗎?
      2. Universal App 要寫的話,沒你想像中的方便 XDDD
      3. 裡面手機展示,竟然還有Nokia Logo….. XDDD
    • 微軟進攻辦公室戰場大武器 - SurfaceHub
      • 簡單講就是超大的平板Surface,支援觸控,相機跟麥克風.
      • 可以當電子看板,會議系統甚至放在會議室都很適合作為腦力激盪或是一些會議功能.
    • 更酷的AR應用 - HoloLens
      • 更強大的AR(互動虛擬實境)可以讓數位資訊進入你的生活中.個人認為HoloLens的眼鏡相當的酷,功能看起來挺完整的.
      • 相關整理報告
  • [Java] 這裏整理一下 2015/01 TWJUG聚會的相關資訊
  • [其他/綜合] 一些不好歸類的
  • [Heroku] 關於Web Application 的logging system
    • 本來有點在煩惱要如何查看在Heroku server端的log 資訊,因為Heroku 身為PAAS是不會儲存變動的檔案(除非submit進入git的檔案)
    • 本來打算log 全部進DB,發現整個loading相當的緩慢.
    • 原來Heroku log本身就會列印出Server side的 console output,所以這邊挺方便的.還支援continue stream log
    • 更多細節可以查看Heroku Logging 文件
  • [XMPP][AMQP] 關於這兩個系統最大的差異

[Golang] 相當好用但又要注意的defer

image

  • 經常在處理檔案的開關必須要注意到file open就一定要有搭配的 file close.但是如果有很多的case,搭配著很多的return.那是不是就得在每個地方寫上fclose?
  

func FileProcess() error {
    //開啟檔案
    f, err := os.Create("/tmp/dat2")
    check(err)
    
    //在這裡呼叫 defer f.Close(),如果有參數會這時候讀入
    defer f.Close()
    
    if CASE1 {
        Do something        
        //這時候會執行 f.Close()
        return  errors.New("Error Case2")
    } else if CASE2 {
        Do something
        //這時候會執行 f.Close()
        return errors.New("Error Case2")
    } 
    // 就算之後要增加新的case,也不用擔心要補 f.Close()
    
    //這時候會執行 f.Close()
    return nil
}

  • Golang裡面有個很方便的function 叫做defer,他執行的時間點會是在你離開目前的function.
  • 不過這裡需要注意的是有兩個地方:
    • 變數的傳遞,會在呼叫defer的時候傳入.所以他並不是很簡單的直接移到最後呼叫
      • 根據GoDoc Defer: The arguments to the deferred function (which include the receiver if the function is a method) are evaluated when the defer executes.
    • 呼叫與執行defer採取的是LIFO.
  • 參考這篇文章
  • 結論:
    • defer最好還是使用在fopen與fclose比較不會有問題.
    • 如果有參數要帶,千萬要想清楚當時參數的順序與是否有其他問題會發生.
  

package main

import (
	"errors"
	"fmt"
)

func useAClosure() error {
	var err error
	defer func() {
		fmt.Printf("useAClosure: err has value %v\n", err)
	}()

	err = errors.New("Error 1")
	fmt.Println("Finish func useAClosure")

	return err
}

func deferPrintf() error {
	var err error
    //呼叫的時候會把參數帶過去,所以err是nil
	defer fmt.Printf("deferPrintf: err has value %v\n", err)

	err = errors.New("Error 2")

    //注意這裡是LIFO,所以呼叫會是43210
	for i := 0; i < 5; i++ {
		defer fmt.Printf("%d ", i)
	}
	fmt.Println("Finish func deferPrintf")
	return err
}

func main() {
	useAClosure()
	deferPrintf()
}

/* output
Finish func useAClosure
useAClosure: err has value Error 1
Finish func deferPrintf
4 3 2 1 0 deferPrintf: err has value 
*/
</pre>

[Golang][iOS][程式設計週記].. 2015第二週.. 20150116

前言:

這個禮拜,總算有點時間可以去參加GTG.也順便多花了點時間研究Go….

筆記:

  
package main

import "fmt"
import "sort"

func main() {

    test := []string{"hello", "world", "z"}
    
    fmt.Println(sort.SearchStrings(test, "hello")) //return 0 which hello could be insert in index 0, before "hello". The same string insert in front of it.
    fmt.Println(sort.SearchStrings(test, ".DS"))   //return 0, ".DS" will be insert in index 0. Not cannot find (-1)
    fmt.Println(sort.SearchStrings(test, "world")) //return 1, reason the same with hello
    fmt.Println(sort.SearchStrings(test, "yDS"))   //return 2, "yDS" before "z" so insert in index 2.

/* Output
0
0
1
2
*/
}
  • [Go gen] A type-driven code generation in Go
    • Git位置
    • 在Go Miami meetup的 demo
    • 簡單介紹:
      • gen 提供了許多好用的type structure,也就是有點類似提供了generic 的功能.你可以透過他的資料型態做更多的資料處理. 在code撰寫上也很簡單.只需要在你的資料前面打上annotation.
  
// +gen slice:"Where,GroupBy[string],Select[Dollars]"
type Person struct {
  Name, Office string
}

func main() {

    ny:= func(p Person) bool {
        return p.Office == "New York"
    }

    fmt.Println(persons.Where(ny))
}

[研討會心得]Golang Taipei Gathering #12 etcd in IoT /go generate

image

前言:

本來還在思考要不要參加,但是剛好gtg slack上面有人願意把票讓出來.就趕快來聽聽.此次的相關資料在這裡

研討會筆記:

  • [POGA]Go Generate, trick to write
    • Ruby
      • 適合拿來寫 DSL
      • Stirng/HASH Anywhere
      • lack of “syntax eror”
    • GO
      • sort 不支援int64 sort, 其實只是多寫成4 lines :).
        • 參考這篇

          Because it’s four lines of code:

          type int64arr []int64

          func (a int64arr) Len() int { return len(a) }

          func (a int64arr) Swap(i, j int} { a[i], a[j] = a[j], a[i] }

          func (a int64arr) Less(i, j int) bool { return a[i] < a[j] }

          Float64 is the more common float, int is the more common it, so both have predefined versions of this.

      • self-refererencial function
      • struct tag using reflect is slow, don’t use it in DSL.
      • go generate 僅僅是regex來替換而非parser
        • “go get” don’t run “go generate” for you
      • slide: http://www.slideshare.net/poga/gtg12
      • 與講者額外的談話:
        • struct tag 可能會發生問題.. 由於json tag 是會被go compiler skip,但是極有可能會發生一些錯誤
          • tag 內名稱寫錯而永遠讀不到json的內容
          • 不小心把一些語法寫在雙影號外面.(e.g. omit…)
          • 寫錯不會造成整筆資料都是空的,而是某個欄位會變成空的.這就比較麻煩.
        • 關於go generate 使用實例:
          • 把他當成shell script
          • 自我檢查,比如slide裡面的auto error
  • [HAWK]miicasa etcd for IoT
    • What is IoT?
      • 物聯網 - 蒐集狀態機
        • 透過簡單的 AND OR NOT的來控制.
        • 舉例而言:
          • 設計兩個開關與一個燈泡,透過XOR來控制燈泡.可以把開關放在房間內與門口.
          • 類似 Key-Value的處理法
    • etcd
      • 簡單,安全,快與可信賴
        • 1000 per/s
      • 效能測試:
        • 56 kB 10萬條長連線, 15G Ram.
          • 5k 1.6s
          • 10k 2.4s
        • etcd heart bit
        • HTTP heart bit
        • 不同語言效能
          • C -> 50萬
          • Go -> 15萬
      • demo:
        • 講者準備一個感知元件,當收到有人經過會去把燈泡做開關的動作.
        • 一個PIR(Peson In Rear) 的sensor搭配sender.一遇到信號就連上etcd去變更資料.
        • 一個類似smart plug的接受端,透過etcd的wait來等待信號的改變.
          • 直接用etcd wait (有keep alive)
          • Http本身也有keep alive,斷掉的話重新連線監聽
      • 心得:

        • etcd有cluster的概念,可以使用在個別的IoT設備上.其實kktix的小神器掃QRCode幾就已經把它整合redis進去,然後定期同步.
        • 講者的使用方式主要偏重於插電的IoT(Internet of Thing),不過我認為在電池方面應該會更加的省電,因為使用http的鏈結電量應該遠遠比其他方式少.
        • 大陸方面也有流行跟微信接口的IoT,這樣就不需要自己架設相關的伺服器.jabberd2雖然不難架,但是要管很累.