[Java][Golang][Python][程式設計週記].. 2015第一週.. 20150109

前言:

主要紀錄一些網路上查到的東西,實作上應該會有更多文章出現….

筆記

[Golang]關於martini架構的更深一步了解

image

前言:

最近開始深究Go的webframework martini.慢慢開始會寫更多的東西出來.

筆記:

以下敘述的方式,會根據我想要達成的目標依序紀錄一下:

  • [JSON] 解決martini JSON的資料解析(parse)
    • 不論是Martini或是 http.Request原本基本都會是使用JSON.Unmarshall來處理.
    • 這裏需要注意的是,跟當初在處理mongodb的資料一樣.變數的名稱不可以全部是小寫,但是json資料名稱需要全部都是小寫.
    • 如果不小心把變數名稱全部打成小寫,會無法正確的Unmarshall資料.
  

type Response2 struct {
    Page   int      `json:"page"`
    Fruits []string `json:"fruits"`
}

str := `{"page": 1, "fruits": ["apple", "peach"]}`
    res := &Response2{}
    json.Unmarshal([]byte(str), &res)
    fmt.Println(res)
    fmt.Println(res.Fruits[0])
  • [martini-render] 關於martini 顯示json的顯示部份.原本encoding/json能處理大部分的事情.但是要能完整顯示http status code 與json內容的話.我還是選擇了martini-contrib/render
  
    render.JSON(400, map[string]interface{}{"result": "success"})
  • [Martini map]接下來問題是,如何在各個martini handler中,去傳遞你要的變數或是如何把資料庫加入.
    • 原本是應該要直接使用martini.Use(DB()) 然後再去接 DB 的起始martini.handler即可.參考這裡
    • 但是想要做成可變動的資料庫格式(in-mem DB, mongodb 共存) 所以還是直接丟整個變數比較好.類似作法參考
  
var db SomeDB{} 
//將變數透過martini 傳到各個handler
m.Map(&db)
...


//新增一個變數參數就可以使用
func someHandler(params martini.Params, r render.Render, db *SomeDB) {
....
}

相關文章:

[Java][Heroku][程式設計週記] 新年快樂...來寫code吧.. Go-martini跟 Java Srping Boot

image

前言:

新年新希望…. 繼續寫程式啊…. 之後要把Go Web Server逐漸到真的能使用的部分.

筆記:

  • [Golang][Heroku] 將buildpack upgrate到Go1.4
    • 最近的需求,將Go拿出來重新的翻了一下.除了之前發現沒有更新到Go1.4之外.也發現原來之前透過martini寫出的REST server並不完全是JSON的格式.於是最近開始把Go-herokuo-server翻了一下.
    • 以下紀錄如何將你的heroku更新到1.4
      • 重新跑godep
      • 記得將godep目錄下的檔案全部一併更新上去
    • 或是可以參考kr/heroku-buildpack-go
  • [Golang]關於Json資料的Get/Post處理
    • 發現martini原先雖然有做REST API但是並沒有針對JSON資料來處理.而要處理JSON的資料其實在Go裡面還是有一些地方要處理.
    • 幾個值得注意的地方如下:
      • 從網頁抓來的資料可以由http.Request.Form或是http.request.Body抓來處理.
        • Request.Form 資料可以從 curl -X POST -d “DATA” “http://address”
        • Request.Body 資料不僅僅可以抓 curl的資料,也可以抓取http.NewRequest(“POST”, url, bytes.NewBuffer(jsonStr))來的資料.
        • 抓取來的資料都可以透過map interface來接,再慢慢去處理.
        • 如果JSON資料比較複雜類似 { A:a1 B:[ { B1: b1, B2:b2}]} 就透過以下邏輯來解決
          • 先透過第一層map拿到B內容 [ { B1: b1, B2:b2}]
          • 透過 array interface拿到 { B1: b1, B2:b2},記住內縙 ary[0]
          • 再透過map接過來繼續解出其他的內容.
    • 參考資料:
    • 以下把部分程式碼擷取出來:
  
//資料來源
//curl -X POST -d "{ \"name\"" : \"that\", \"num\": \"3\"}ttp://localhost:5000/fruits"

// 透過Request.Form的資料
r.ParseForm()

var dat map[string]interface{}

for key, _ := range r.Form {
	fmt.Println("r.form")
	fmt.Printf("key = ")
	fmt.Println(key)
	err := json.Unmarshal([]byte(key), &dat)
	if err != nil {
		fmt.Println(err.Error())
	}
}

for key, value := range dat {
	fmt.Println("Key:", key, "Value:", value)
}


// 透過Request.Body再把Json資料Unmarshall
body, err := ioutil.ReadAll(r.Body)
if err != nil {
	fmt.Println("read error")
}
fmt.Println(body)
fmt.Println(reflect.TypeOf(body))
fmt.Println(string(body))

var dat map[string]interface{}

err = json.Unmarshal(body, &dat)
if err != nil {
	fmt.Println("Unmarshal error")
}

//Handle Data Like
////Data: `{"name":"test1", "num":"2", "data": [{"data1": "value1", "data2": "value2" }] }`

err = json.Unmarshal(body, &dat)
if err != nil {
	fmt.Println("Unmarshal error")
}

//Get specific colume as array interface
//[{"data1": "value1", "data2": "value2" }]
map_body := dat["data"].([]interface{})

var dat2 map[string]interface{}
// Get first one from array (dat2 is map)
//{"data1": "value1", "data2": "value2" }
dat2 = map_body[0].(map[string]interface{})

//Handle dat2 as map to get rest data.
	
  • [iOS] 寫了Server方面,當然要寫client的方式
    • 讀取很方便,NSURLConnection就可以處理,而且抓來的Json會直接放進map處理
    • 寫入有一點小複雜,必須寫使用Diectionary處理你要處理的資訊後,再透過NSURLConnection來啟動.
  

- (IBAction)JsonSend:(id)sender {
    NSMutableURLRequest *request = [NSMutableURLRequest
                                    requestWithURL:[NSURL URLWithString:@"http://127.0.0.1:5000/fruits2"]];
    
    //透過NSDictionary放入資料,右邊是Key左邊是Value
    NSDictionary *requestData = [[NSDictionary alloc] initWithObjectsAndKeys:
                                 @"Banana", @"name",
                                 @"3", @"num",
                                 nil];
    NSError *error;
    NSData *postData = [NSJSONSerialization dataWithJSONObject:requestData options:0 error:&error];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:postData];
    
    
    NSURLResponse *requestResponse;
    NSData *requestHandler = [NSURLConnection sendSynchronousRequest:request returningResponse:&requestResponse error:nil];
    
    NSString *requestReply = [[NSString alloc] initWithBytes:[requestHandler bytes] length:[requestHandler length] encoding:NSASCIIStringEncoding];
    NSLog(@"requestReply: %@", requestReply);
}

- (IBAction)JsonGet:(id)sender {

    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://127.0.0.1:5000/fruits/1"]];
    
    __block NSDictionary *json;
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                               json = [NSJSONSerialization JSONObjectWithData:data
                                                                      options:0
                                                                        error:nil];
                               NSLog(@"Async JSON: %@ id=%@", json, json[@"id"]);
                           }];

}
  • [Eclipse][Java] 復原整個Java Srping Boot的開發環境
    • 前言:
      • 之前因為Eclipse ADT從22.x更新到了23,使得我的eclipse無法正確跑Android.看了許多人的建議.看來只能夠把Eclipse砍掉重裝.不過也讓我的Java Spring Boot整個開發環境就跑掉了.
      • 這一篇記錄一下會遇到哪些問題,並且把問題的解決方式也記錄一下.
    • 問題一: JRE環境跑掉
      • 問題內容
        • 無法正確的編譯Java Spring的專案
      • 解決方法:
        • 由於之前在跑Spring專案的時候,有使用到Java8的一些函示.所以有裝Java8.JRE跑掉會有以下的狀況.
        • [Preference]->[Java]->[Installed JREs] 發現是空的
        • 按下 [Add]->[Stardard VM]->Directory 選擇 [Library/Java/JavaVirtualMachines/JDKversion]
    • 問題二: 無法執行junit
      • 問題內容:
        • 按下junit來跑測試的部分的時候,發現都會出現“An internal error occured during Launching”
      • 解決方式:
        • 這邊花了一點時間才解決問題.
          • Go to help
          • Install New Software
          • Work with: Juno
          • Programming languages (expand it)
          • Install “Eclipse Java Development Tools””
          • Restart
          • 參考這裡
    • 順便在三地記錄一下,要如何跑Java Spring Boot專案
      • 專案:
        • [Run] -> [Java Application] -> Machining Item -> [Application]
      • 測試部分:
        • 指向該junit檔案(*.java) [Run]->[Junit Test]

[UNIX][python][Golang][程式設計週記] 20141231

前言:

接下的時間可能會比較忙碌,盡量也會多花一點時間玩Go…

筆記:

[Golang]關於Slice在Append的一些發現

image

前言:

當初主要是RUST在官網上提出他們可以避免掉std:vector.push_back造成的referene 問題. 於是我也很好奇,究竟Golang會怎麼樣處理這樣的問題. 也由於Go本身把vector拿掉,我們就用Slice來試試看.

筆記:

image

Slice 本身的結構包含資料本身,長度(len)與容量(cap),根據Slice Internal Document裡面提到的.而且操作slice的append的時候,會根據你目前的容量(cap)來決定是否要重新分配記憶體位置.

比起std::vector好的是,如果記憶體重新分配了,原先參照的參數不會得到空的記憶體位置,而會變成是複製的內容. 但是要注意的是,參照的變數就不會跟著變動了. 這聽起來就是比較安全一點,不過程式不會造成pointer to null並不代表比較好,因為在這種狀況下.所參照的數值已經被修改,你可能會遇到更不能預測的問題.

所以比較優雅的方式,還是事先要保留足夠的資料.避免append造成的資料重新建立.

奇怪的狀況,cap增長的大小根據compiler的不同

我本來是很清楚這樣的狀況,直到我把我以下的程式跑在本地端(Mac/Win)還有遠端的Golang Playground發現結果不一樣了.

是的! 靚過第一次slice append之後,cap(slice)增長的數值竟然不一樣?? (Playground是2,本地端是1) 一樣的狀況.類似的操作在c++ std::vector 就沒看到 (Win/Mac/Coliru online compiler) 增加過後的的cap都維持為”1”. 這裏有參考的C++程式碼.

於是我在Stackoverflow詢問了這樣的問題,也引起了一些人的注意,幫我把問題發到了Golang上面.雖然沒有辦法說服大家把這樣類似的問題放入spec或是warning,但是真的提醒大家,真正在使用slice的時候,必須像使用std::vector一樣的小心.最好的方式是不要參照,如果真的要參照的話,也建議使用保留的slice大小來避免記憶體重新的分配所造成的參照失效.

以下是完整的Golang 測試程式碼

  
package main
 
import "fmt"
 
func main() {
	var a []int
	var b []int
	fmt.Printf("a len=%d, cap=%d \n", len(a), cap(a))
	a = append(a, 0)
	b = append(b, 0)
	p := &a[0]
	
	fmt.Printf("a[0] = %d pointer=%d, len=%d, cap=%d, p = %d \n", a[0], &a[0], len(a), cap(a), *p)
	a[0] = 2
	fmt.Printf("a[0] = %d pointer=%d, len=%d, cap=%d, p = %d \n", a[0], &a[0], len(a), cap(a), *p)
	/*
		a[0] = 0, p = 0
		a[0] = 2, p = 2
	*/
	var c []int
	var d []int
	fmt.Printf("c len=%d, cap=%d \n", len(c), cap(c))
	c = append(c, 0)
	d = append(d, 0)
	p2 := &c[0]
	fmt.Printf("a[0] = %d pointer=%d, len=%d, cap=%d, p2 = %d \n", c[0], &c[0], len(c), cap(c), *p2)
	c = append(c, 1)
	c[0] = 2
	fmt.Printf("a[0] = %d pointer=%d, len=%d, cap=%d, p2 = %d \n", c[0], &c[0], len(c), cap(c), *p2)

	/* 
		c[0]=0, p2 = 0
		c[0]=2, p2 = 0
	
	  in http://play.golang.org/p/DuClFZt2cK, the cap increasement by machine dependency.
		c[0]=0, p2 = 0
		c[0]=2, p2 = *2*
	  
	*/
}

[UNIX][python][Golang][程式設計週記]20141227

前言:

今年年底到數第二週,可以開始深入研究一些自己有興趣的東西.本週主要研究signal的處理,regex與新程式語言RUST學習,當然其中也有一些新的MOOCs學習.加上這個禮拜週六要補班,所以整個內容應該會比較多一點.

筆記:

  • [Unix]關於Signal PIPE 更深入的研究
    • 前言:
      • 雖然加上了signal pipe的handler但是並沒有真正的測試到類似的狀況.
      • 這個禮拜應該會花一些時間好好的研究詳細的內容.
    • 筆記:
      • 關於Signal:
        • signal就是去接受或是傳送process間的溝通方式.系統設定好,也比較為人所知的就是 SIGINT (就是ctrl + c), SIGTERM(process 結束)或是 SIGKILL(被 kill,不過系統預設是不能catch 這個signal). 而這裡探討的是如何把接受到signal要做的一些處理做起來.這裏有更多的說明
      • 如何處理Signal:
        • 基本上會收到任何signal,表示你的程式正在收到不可預料的狀況(以系統的signal為例),但是無法明確的了解哪些問題的發生.通常會建議把一些資源回收後,準備重啟的相關動作.
      • [12/22]關於測試sigaction 的部分:
        • 可以使用 kill -s (signal) process_id 來傳送signal
        • 不過並不是完全可以接收的到.
          • 以下是接受的清單:
            • SIGINT (02)(handle ctrl + c signal)
            • SIGSEGV (11)
            • SIGALRM (14)
            • SIGTERM (15)
            • SIGSTOP (17)
            • SIGTSTP (18)(handle ctrl + z signal)
          • 以下接收不到:
            • SIGSYS (12)
            • SIGPIPE (13)
            • SIGCONT (19)
      • [12/23]於是我把我發現的事情,整理過後試著去stackoverflow詢問.得到了回應是他們測試是可以的,可能是我底層元件出了問題.
        • 經過測試真的如網友回應的,看來底層的元件有把SIG_PIPE收走,造成我在上層無法接收加以處理. 得繼續研究如何解決類似的問題…..
      • [12/24]最後網友提出解決方式就是在3rd party library 後面去加入sigaction,這樣就可以了.
      • 參考:
#include 
#include 
#include 
#include 

void handle_pipe(int sig)
{
    printf("SIG_PIPE happen, error code is %d", sig);
    exit(0);    
}   

int main(int argc, char **argv)
{
    struct sigaction action;
    sigemptyset(&action.sa_mask);
    action.sa_handler = handle_pipe;
    action.sa_flags = 0;
    //not work
    sigaction(SIGPIPE, &action, NULL);   //Not work with kill -13 process_id
    //works well
    sigaction(SIGINT, &action, NULL);    //work with kill -2 process_id
    sigaction(SIGSEGV, &action, NULL);   //work with kill -11 process_id
    sigaction(SIGALRM, &action, NULL);   //work with kill -14 process_id
    sigaction(SIGSTOP, &action, NULL);   //work with kill -17 process_id

    while(1)
    {
        sleep(1);
    }
}

</pre>            
            
- [Python][Unix]深入研究regex (Regular Expression) (1)
    - 前言:
        - 主要是在伺服器的log上面,忽然有需要抓出某些特定的資訊.由於因為限定某些時間之內,所以無法改server,所以只好開始搞搞regex.
        - 不過當時手邊沒有一個可以快速找到內容並切輸出的內容regex語法,所以當時還是用一些巨集加上檔案的轉換才搞定.
        - 東西忙得差不多,決定把這個整理成一個python檔案.可以幫助以後快速的分析並且抓出需要的資料.
    - 筆記:
        - 首先關於regex,根據[鳥哥Linux的私房菜](http://linux.vbird.org/linux_basic/0330regularex.php)上免得說明.其實可以直接透過grep來完成.不過我沒辦法完成太複雜得,而且又牽扯到字串內的逃逸字串問題,所以這部分僅僅帶過.
            - grep -n 'REGEX' input_file
       - 後來決定使用python的[regex](https://docs.python.org/2/library/re.html)功能,其實提供的功能可以替換跟找出來並且轉換成list.已經很夠用了.
       - 以下是一段python找出檔案內電話資料格式的範例(以台灣室內電話與行動電話為例)      
    - 相關資源:
        - Java script 去顯示regex 語法示意圖
            - [http://jex.im/regulex](http://jex.im/regulex)
        - regex eval可以幫你找出特定文字內符合你輸入的regex內容.
            - [http://regexpal.com/](http://regexpal.com/)

 #python sample
import os
import re

 # filename variables
filename = 'data//test_regex.txt'
newfilename = 'result.txt'

 # read the file
if os.path.exists(filename):
    data = open(filename,'r')
    bulkemails = data.read()
else:
    print "File not found."
    raise SystemExit

 # regex to get phone
 # (01)2345-6789 , (01)23456789
 # 0123456789 
 # 0911-234-567

r = re.compile(r'(\b(((\d{10})|([\(]??0\d{1}[\)]??\d{4}[\-]??\d{4})|(0\d{3}[\-]??\d{3}[\-]??\d{3})))\b)')
results = r.findall(bulkemails)
emails = ""
for x in results:
    print str(x)+"\n"       
- [Python]關於raw string的用法與轉換 - 前言: - raw string 是python 裡面代表著原始字串的內容,其中不會將逃逸字串作轉換 (ex: \" -> ") - 在regex裡面,我們需要最原始的字串內容來表達搜尋的資料. - 這邊紀錄一下關於字串轉換這裡會遇到的問題. - 筆記: - 在這一篇的[stackoverflow裡面](http://stackoverflow.com/questions/2428117/casting-raw-strings-python),其實有不少的方式可以解決這件事情. - 有人提出可以透過 string.encode('string-escape') 但是對於這邊的系統會出現字串加上了unicode字元,就算改成string.encode(''unicode-escape')一樣不行. - 只能夠過字元 mapp來達到簡單的轉換,原始碼來自同一個網頁....
                                               
escape_dict={'\a':r'\a',
           '\b':r'\b',
           '\c':r'\c',
           '\f':r'\f',
           '\n':r'\n',
           '\r':r'\r',
           '\t':r'\t',
           '\v':r'\v',
           '\'':r'\'',
           '\"':r'\"',
           '\0':r'\0',
           '\1':r'\1',
           '\2':r'\2',
           '\3':r'\3',
           '\4':r'\4',
           '\5':r'\5',
           '\6':r'\6',
           '\7':r'\7',
           '\8':r'\8',
           '\9':r'\9'}

def raw(text):
    """Returns a raw string representation of text"""
    new_string=''
    for char in text:
        try: new_string+=escape_dict[char]
        except KeyError: new_string+=char
    return new_string
- [RUST][MOOCs] 新的系統程式語言 RUST 線上課程與資料 - 前言: - 主要是[FB MOOCs社團上面的推薦](https://www.facebook.com/groups/courserazh/permalink/852795524760307/)的[課程作業系統](http://rust-class.org/index.html),但是特別的是用RUST上課.所以順便來看看號稱"安全,支援並行並且實用"的程式語言是什麼樣的架構. - 話說,介紹網頁寫得相當的棒.讓我引用原文從[官方網站](http://www.rust-lang.org/) - **Rust** is a systems programming language that runs blazingly **fast**, **prevents** almost all **crashes***, and **eliminates data races**. - 筆記: - 這裏主要只紀錄一下相關資訊,其他比較深入的內容可能就會另外弄成一篇. - 相關資訊: - [線上課程- OS - 使用RUST](http://rust-class.org/index.html) - [RUST官方網站](http://www.rust-lang.org/) - [trello RUST rush task](https://trello.com/b/uwzd0qUZ/rust-rush) - [MOOCs] 模型思考開課 - 有中文字幕的Model Thinking 開課一段時間,看了幾個slide挺有趣的.似乎可以幫助思考邏輯的提升. - [課程在這裡](https://class.coursera.org/modelthinkingzh-001)... 雖然有點晚~但是知識才是重點.... :) - [Python] 關於更多的python程式介紹網頁... - [https://inventwithpython.com/chapters/](https://inventwithpython.com/chapters/) - [Android][這一篇文章](http://blog.danlew.net/2014/11/26/i-dont-need-your-permission/)提到Android Intent其實藏有許多的問題 - 在於Intent不需要使用者關於權限的同意.所以即便項範例中舉例說每天半夜盜用妳電話打到某個地方.你也完全蒙在鼓裡. - 不過這篇文章受到大家的注意的是,英文翻譯的問題,最後竟然是由母語是英文的外國人來做翻譯: - The reason you need permission is because with this code you can initiate a phone call at any time without user action! If my app had this permission I could be calling 1-900-CAT-FACTS at 3 AM every morning and you'd be none the wiser - [Golang] 有趣的網址收集,大多是從Golang.tw的討論群組上看到的 - [這一篇介紹](http://jasonwilder.com/blog/2014/02/04/service-discovery-in-the-cloud/)許多有趣的Opens Source Services Discovery 其中相當多是Go寫的 - kite - A RPC services :[介紹網址](http://blog.gopheracademy.com/birthday-bash-2014/kite-microservice-library/)[Source code](https://github.com/koding/kite) - 順手把Go 從1.3升到1.4,不過會發現許多library有不能與1.4共用.所以go\src下面幾乎所有的檔案都得砍掉重新抓. - 錯誤訊息: "... object is [darwin amd64 go1.3 X:precisestack] expected [darwin amd64 go1.4 X:precisestack" - Gin - A small REST microserver :[介紹網址](http://txt.fliglio.com/2014/07/restful-microservices-in-go-with-gin/) :[Source Code](https://github.com/gin-gonic/gin) - 感覺比[martini](https://github.com/go-martini/martini)更小.. 還得多多的實驗.不論如何.. 有了更多的選擇.... - 找尋的時候,發現有新的web framework [flotilla](https://github.com/thrisp/flotilla) 根據作者在reddit上面的講法,他希望能做出更具有延展性的Web Framework. Engine是可以抽換的. - [作者在reddit的討論](http://www.reddit.com/r/golang/comments/2hg50x/flotilla_set_your_fleet_afloat/) - [介紹網址](https://thrisp.github.io/flotilla/) - [Facebook Go Group](https://github.com/facebookgo/)隱藏的群組,不過有不少程式碼在Github上面. - 開始找一些可以解釋Golang比C/C++好的文章,以下是一些列表: - [Go: 90% Perfect, 100% of the time.](http://talks.golang.org/2014/gocon-tokyo.slide#1) - [Hacker News上面討論C跟Go的比較](https://news.ycombinator.com/item?id=4110480) - [某個人把php搬移到Go的心路歷程](http://tech.t9i.in/2013/01/why-program-in-go/) - [Powered by Go,介紹更多Go比起C/C++的優勢](http://talks.golang.org/2013/oscon-dl.slide#1)