[Golang][Martini]在Martini-render上面的layout/template套用

前言: 學習架設Golang Web Services 的時候,也需要有後台網頁管理介面.這時候就需要有樣板來套.才能讓網站架設起來比較快. 筆記: 以下的部分會提到如何使用,我個人使用習慣. 不會將所有的程式碼都貼出來,但是會顯示部份的整理過的資料. 關於Martini的layout: 網頁上的資料部分,可以拆解成兩大部分: 不可以抽換,使用layout替換 (ex: layout.tmpl) 舉例: <HTML><HEAD> 甚至是CSS JS都可以. 需要用程式來表示的部分,用render來顯示 (ex: hello_world.tmpl, layout_hello.tmpl) 舉例: table content或是資料庫裡面的資料. Layout file layout.tmpl <!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Layout sample</title> </head> <body style="margin: 20px;"> <h1>This is a layout sample</h1> <!-- 可以被替換的部分放這裡 --> </body> </html> 其中 `` 將你要顯示的tmpl部分全部換到這邊. 接下來要處理的部分拆解到hello_world.tmpl. <CENTER> Hello </CENTER> 接下來另外一個需要處理的到layout_hello.tmpl. <CENTER> This is another layout Hello </CENTER> 接下來就要提到Golang處理layout的部分. 如何使用Layout: 提到Golang處理的部分,先看看在一開始martini啟動的部分 ..... func main() { m := martini.Classic() // 將所有預設的layout都先設定到"layout.tmpl" m.Use(render.Renderer(render.Options { Layout: "layout", })) ..... m.Run() } 這邊要記住,預設的目錄都會在templates下面. 要顯示的時候可以使用以下的方式. // 使用hello_world.tmpl m.Get("/", func(r render.Render, db *mgo.Database) { display_name := "John" r.HTML(200, "hello_world", display_name) }) 如果不同的entry point 要使用不同的layout呢? 有一些時候,網站開始變大之後.layout 的版型也開始變多了.這時候可能需要動態的去變你要套用的layout.原本的martini-render 就提供可以在render.HTML裡面加上 HTMLOptions.其實也就是加上你要指定的layout. // 使用hello_world.tmpl,並且套上layout_hello.tmpl m.Get("/", func(r render.Render, db *mgo.Database) { display_name := "John" r.HTML(200, "hello_world", display_name, render.HTMLOptions{Layout: "layout_hello"}) }) 相關鏈結: GoDoc: martini-render 這一篇是GoDoc不得不看.. GoDoc: template 關於http/template,不過martini-render是架設在他之上.可看可不看. GO TUTORIAL WITH MONGODB ON HEORKU 是一篇tutorial,不過對於martini-render有一些介紹. Hack martini-render 很推薦看這一篇,基本常識都會了解. 初學 Golang 30 天(二十八)Router,...
繼續閱讀

[MongoDB]More study about mongodb and mgo 3 - logical operator and like

Preface When we trying to use MongoDB, the requirement comes more and more complex and diversity. Here is some note during my implement. Multiple condition in MongoDB Query It is very easy to find data in MongoDB, but how about multiple condition such as “AND” and “OR” ? AND OR in MongoDB It is very easy to find “AND” support in MongoDB, but how to apply in mgo (MongoDB driver in Go)? // Find user name is John and Contry is US. var alldb []User UserCollection.Find(bson.M{"$and": []bson.M{bson.M{"name": "John"}, bson.M{"Contry": "US"}}}).All(&alldb) Please note: the $and need combine an array of bson.M. // Find CONDITION_A and CONDITION_B bson.M{"$and": []bson.M{ CONDITION_A, CONDITION_B }} So, it is similar with “OR” ($or), detail doc is here. // Find CONDITION_A or CONDITION_B bson.M{"$or": []bson.M{ CONDITION_A, CONDITION_B }} Make it more clear in code. // Find user name is John or Tom. var alldb []User UserCollection.Find(bson.M{"$or": []bson.M{bson.M{"name":...
繼續閱讀

[Golang]關於Channels的控制一些要注意的事項(二)

##前言 前一篇的一些討論後,接下來有一些更容易出錯的部分可以討論.主要focus Goroutine跟 defer ###Goroutine Closure 主要是這一篇部落格帶出的問題: 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 } } 根據以上的部分,印出的結果不會是 “a”, “b”, “c”.而是 “c”, “c”, “c” 原因是 goroutine 變數會參照到go func 跑的時候. 如果修改成以下就可以避免這個問題: func main() { done := make(chan bool) values := []string{"a", "b", "c"} for _, v := range values { go func(obj string) { fmt.Println(obj) done <- true }(v) } // wait for all goroutines to complete before exiting for _ = range values { <-done } } 由於他的順序會是 go func(v) 之後才執行,所以其變數內容會先傳過去而不是跑道fmt.Println(v)才取得. 更多跟goroutinem與closure有關的資訊請看這裡Go: FAQ 參考資料 Effective Go: Channels 官方Effective Go文件,一定要熟讀. Go FAQ: hat happens with closures running as goroutines? A Go Gotcha: When Closures and Goroutines Collide
繼續閱讀

[Android]關於JNI的學習筆記

前言 上個禮拜在Android Studio 1.1 把JNI搞定之後,接下來就是把JNI的內容去完成.其中有許多小技巧與眉眉角角的地方需要紀錄一下. 筆記內容 關於Android.mk 與 Application.mk 的部分 (2015/10/21 update) 關於Android Studio與JNI的發生ld.exe crash 如果在Android Studio要去load其他的jni static library,在Windows上面有時候會發生ld.exe crash的問題.這時候只要打開”Build Variants”-> 把”Build All”,改成看你現在需要哪一種(Android 手機就是 arm-Debug,模擬器就是x86-Debug). 就可以解決. (2015/10/20 update) 關於STL部分 如果有用到STL的支援,主要都是修改Application.mk,不是改在Android.mk中. 這樣才能一次改到所有的檔案,避免A檔案過,B檔案不過. APP_STL := stlport_static 參考: Using the STL with Android NDK C++ 增加 C++ 與 CPP11 支援 新增以下到 Application.mk APP_STL := stlport_static APP_CPPFLAGS += -std=c++11 讀取其他資料夾與一次讀取所有的cpp 新增以下到 Android.mk LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/../../../../../../source/*.cpp) 關於JNI資料的轉換部分 C++ char* 與 JNI jstring 的轉換 *jstring to char ** char* jstringTostring(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { rtn = (char*)malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } env->ReleaseByteArrayElements(barr, ba, 0); return rtn; } char* to jstring jstring stoJstring(JNIEnv* env, const char* pat) { jclass strClass...
繼續閱讀

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

##雜七雜八感言: 最近搞完一些Golang部分,有開始跑各個平台的cross platform的building solution.果然C++跨平台一點都不簡單,真是80%設定環境,20%寫跨平台的code…. ##筆記: [Golang] 關於Golang 有趣的網頁與小工具 GophoerConIndia 許多Go 的大老都參加了,挺值得一看. Go on Mobile - David Crawshaw - London Go Gathering 2015 [Apple] 關於 Apple 03/09 發表會 這個禮拜讓蘋果迷最興奮的就是三月的發表會. 裡面有包括了ResearchKit,MacBook更新跟Apple Watch. 兩個跟硬體有關的就沒啥好評論…. ResearchKit 與 HealthKit 根據已經放出的消息,ResearchKit透過兩項(目前已知是手指點擊與聲音)的手機功能,可以提供一些簡單的診斷.並且把這些資料提供給醫療研究機關. 等到詳細資料出來應該會更仔細地研究一下,是否一般廠商有介入的空間. [Android] 在Android Stuido 1.1 上面使用 自從Google 推出 Android Studio 正式版之後,自然而然也開始把Eclipse的力道放輕. 於是要弄新的SDK也變成是一個工程. 所以現在要開發新的cross platform module,所以也必須要在 Android Studio + NDK + JNI 去執行跨平台的 C++ module. 根據最新版的Android Studio 1.1 如果依照著一般的方式來部署NDK會發現以下的問題: WARNING [Project: :app] Current NDK support is deprecated. Alternative will be provided in the future. 找了一堆論壇,其實並沒有一個有系統地整理,直到看到這一篇文章,以下把方法整理一下: 安裝 Android Studio 1.1 下載並且安裝 Android NDK r10d 先到一開始的畫面[Configure]->[settings]->[External Tools] 設定Gradle 設定javah 新增一個NDK Build 類別為NDK Program:C:\ndk\ndk-build.cmd Parameters:NDK_PROJECT_PATH=$ModuleFileDir$/build/intermediates/ndk NDK_LIBS_OUT=$ModuleFileDir$/src/main/jniLibs NDK_APPLICATION_MK=$ModuleFileDir$/src/main/jni/Application.mk APP_BUILD_SCRIPT=$ModuleFileDir$/src/main/jni/Android.mk V=1 Working directory:$SourcepathEntry$ 這樣設定好就可以 複製ndk-r10d 目錄下的sample\hello-jni來使用 會出現一個[c]在上面按下 右鍵跑 “NDK Build”,來製造出.so [App]->[build.gradle]新增: sourceSets.main.jni.srcDirs = [] 然後sync gradle 這時候會發現[C]不見了,就可以跑App 之後要切換就是把上面的那段 comment掉才能build NDK
繼續閱讀

[Android/Golang]Server-Side In-App-Purchase Verification with Google Play on GO

Preface Working on Android application development, you will need to have IAP (In-App Purchase) items. Normally it is simple, if your application is standalone not connect to any server. If you app need connect to server for IAP items (such as game server, database service …), it might have risk that here might be a fake app (or crack app) to fake the purchase command in your app to get privilege action or items. In this case, our server will need to do a sever-to-server side certification with Google Play. Android has done great documentation in their Android portal. But it separate into different part, so I am trying to summarized it here. Hope it help. Google Service Entrypoint - Google API When we want to communication with any Google Service, the only entry point is using Google API Console.. So, here let’s start to connect to Google API. According...
繼續閱讀