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

image

##雜七雜八感言:

令人開心的事情,總算在工作上把某些專案推坑Golang… 可以更專心的學習跟使用Golang…

##筆記:

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

  • [Golang][Gala] Final list of Gala
    • 最後進入final 名單的Gala 2015競爭者,Docket竟然被踢掉了…
  • [Golang][Gala] http://gophergala.com/blog/gopher/gala/2015/02/03/winners/
    • 最後的獲勝者出線了….
  • [Golang]Go Report Card: A report card for your Go application
    • 根據你github上面的go project給予一些分數,評分依據根據gofmt, go vet, go lint與 gocyclo.
    • 挺有趣的,很多時候issue越多並不代表分數不高喔…
  • [Golang] Beego 的教學(tutorial)
    • First,Second, Third, Git
    • 這是之前又介紹過MVC架構的Web Framework Beego的教學.Beego被許多大公司所使用(Weibo, Taobao, Tudou….),算是很棒的架構,有機會可以好好學習.
  • [Golang]Moving from Node.js to Go at Bowery
    • Bowery這家公司把他們平台從Node.js換到Go的經歷.裡面有提到以下的優點:
      • Easy to write cross-platform code, Faster deployment, Concurrency primitives, Integrated testing framework, Standard library and Developer workflow tools are more powerful.
  • [Golang] Go HTTP request router benchmark and comparison
    • 有各種Go Webframework的效能比較,幾個值得注意的事情是net/http 的ServerMux並不會有最好的效能.而martini雖然效能最差,但是擴展性是最高的.
    • 也可以順便知道有多少web framework…. (Beego, go-json-rest, Denco, Gocraft Web, Goji, Gorilla Mux, http.ServeMux, HttpRouter, HttpTreeMux, Kocha-urlrouter, Martini, Pat, TigerTonic, Traffic)
  • [Livehouse.in] 關於c9s的slideshare “Get Merge!”
  • [Golang] Sample Email Sender using SocketLabs
    • 不錯的寄信範例程式使用Go

[Golang] 關於Session的學習

要開始弄martini關於authorication的部分,首先最簡單的除了SSL之外,就使用session了. Martini session 提供了一個相當簡單的方式來使用.

首先可以參考這段教學影片,其實相當的簡單易用,也可以設定哪些網址才需要透過session.

[Golang] 關於Go與CGI的搭配

本來的討論是希望讓Go可以取代PHP在Apache中的地位,主要可以達成以下的結果:

  • 可以多個process,彼此獨立
  • 一個process 出事情不會影響到全部的系統.

是開始尋找有沒有類似的結果,如下:

其他相關的問與答在這裡翻到的:

[Golang] 關於Go來實現RPC相關研究

一但決定要用Go來當成Services,這時候其實有不少solution可以使用.不過要使用哪一種的方式可能有許多可以學習.

先決定使用Golang的RPC的,參考這裡的部分可以先完成第一個部分的RPC Go Server 與 Go Client. 如果要適用RPC Go Server的話,由於他的資料傳遞都有透過gob來marshall過.所以一般其他語言要呼叫的話,是無法直接連接的. 這裏所以如果要其他語言(比如C)要連接Go RPC Server,比較建議使用libgob

所以如果要去除gob造成的影響,另外一個方式是換成JSONRPC.不過差異就是,原先RPC 使用的是Http在Go 裡面,而改成JSONRPC就會變成是Web Socket.要修改成HTTS 上面變得比較困難. 但是其實還是有Gorilla 可以使用.

[Golang] 關於可變參數的傳遞…

主要是想要做出類似以下方式,可以直接將可變參數直接傳下去.

  
func foo(arg ...) {
    fooCall(arg)
}

fooCall(arg ....) {
}

查詢到這篇文章,裡面Russ Cox(Golang開發團隊之一)有提到似乎只能有partial re-warpping.

  
//There's no language mechanism for this, nor is there a Vsprintf func.
//The special case that avoids re-wrapping arguments is tied to 
//the parameter itself, not the type system.  But you can fake it:

	package main
	
	import "fmt"
	
	func vsprintf(f string, args []interface{}, dummy ...interface{}) string {
		dummy = args
		return fmt.Sprintf(f, dummy)
	}
	
	func sprint(f string, arg interface{}) string {
		return vsprintf(f, []interface{}{arg})
	}
	
	func main() {
		fmt.Println(sprint("%d", 5))
	}

//It's hardly elegant, but it works, and the need is rare.
//Russ

code here

[Other] RPI(Raspberry Pi 2.0) 2.0 出來了

這個禮拜比較大的新聞,大概就屬RPI 2.0的規格正式出來,有一倍的記憶體跟六倍的速度,並且可以安裝Windows10

不過我自己還是主要把RPI當作XBMC的多媒體播放器來使用,不過這段影片有把RPI當成任天堂來使用,到也是蠻特別的.

個人覺得有可能的未來如下:

  • 耗電量,應該完全不是走IOT的部分,比較可能是小型電腦與小型伺服器的走向.
  • 由於可以安裝Windows 10,代表著可能性又變得更高,可以朝向家裡的中控中心來思考.或是Cortana的中心.

[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))
}