Archive

Archive for the ‘golang’ Category

Go语言开放工具之Emacs

September 4th, 2012 No comments

原文放在@astaxie 写的“build web application with golang”书里面。

下面只把Emacs里面的拿出来,如果需要参考vim,liteide和Sublime text的请一步 https://github.com/astaxie/build-web-application-with-golang/blob/master/1.4.md

Emacs主要是使用了gocode, speedbar, 并把一些go的命令融合进来。

## Emacs
Emacs传说中的神器,她不仅仅是一个编辑器,它是一个整合环境,或可称它为集成开发环境,这些功能如让使用者置身于全功能的操作系统中

1. 配置Emacs高亮显示

cp $GOROOT/misc/emacs/* ~/.emacs.d/

2. 安装[Gocode](https://github.com/nsf/gocode/)

go get -u github.com/nsf/gocode

gocode默认安装到$GOPATH/bin里面下面,需要把$GOPATH/bin路径设置到系统PATH里面。

3. 配置[Gocode](https://github.com/nsf/gocode/)

~ cd $GOPATH/src/github.com/nsf/gocode/emacs
~ cp go-autocomplete.el ~/.emacs.d/
~ gocode set propose-builtins true
propose-builtins true
~ gocode set lib-path “/home/border/gocode/pkg/linux_amd64″ // 换为你自己的路径
lib-path “/home/border/gocode/pkg/linux_amd64″
~ gocode set
propose-builtins true
lib-path “/home/border/gocode/pkg/linux_amd64″

4. 需要安装 [Auto Completion](http://www.emacswiki.org/emacs/AutoComplete)

下载AutoComplete并解压

~ make install DIR=$HOME/.emacs.d/auto-complete

配置~/.emacs文件

;;auto-complete
(require ‘auto-complete-config)
(add-to-list ‘ac-dictionary-directories “~/.emacs.d/auto-complete/ac-dict”)
(ac-config-default)
(local-set-key (kbd “M-/”) ‘semantic-complete-analyze-inline)
(local-set-key “.” ‘semantic-complete-self-insert)
(local-set-key “>” ‘semantic-complete-self-insert)

详细信息参考: http://www.emacswiki.org/emacs/AutoComplete

5. 配置.emacs

;; golang mode
(require ‘go-mode-load)
(require ‘go-autocomplete)
;; speedbar
;; (speedbar 1)
(speedbar-add-supported-extension “.go”)
(add-hook
‘go-mode-hook
‘(lambda ()
;; gocode
(auto-complete-mode 1)
(setq ac-sources ‘(ac-source-go))
;; Imenu & Speedbar
(setq imenu-generic-expression
‘((“type” “^type *\\([^ \t\n\r\f]*\\)” 1)
(“func” “^func *\\(.*\\) {” 1)))
(imenu-add-to-menubar “Index”)
;; Outline mode
(make-local-variable ‘outline-regexp)
(setq outline-regexp “//\\.\\|//[^\r\n\f][^\r\n\f]\\|pack\\|func\\|impo\\|cons\\|var.\\|type\\|\t\t*….”)
(outline-minor-mode 1)
(local-set-key “\M-a” ‘outline-previous-visible-heading)
(local-set-key “\M-e” ‘outline-next-visible-heading)
;; Menu bar
(require ‘easymenu)
(defconst go-hooked-menu
‘(“Go tools”
["Go run buffer" go t]
["Go reformat buffer" go-fmt-buffer t]
["Go check buffer" go-fix-buffer t]))
(easy-menu-define
go-added-menu
(current-local-map)
“Go tools”
go-hooked-menu)

;; Other
(setq show-trailing-whitespace t)
))
;; helper function
(defun go ()
“run current buffer”
(interactive)
(compile (concat “go run ” (buffer-file-name))))

;; helper function
(defun go-fmt-buffer ()
“run gofmt on current buffer”
(interactive)
(if buffer-read-only
(progn
(ding)
(message “Buffer is read only”))
(let ((p (line-number-at-pos))
(filename (buffer-file-name))
(old-max-mini-window-height max-mini-window-height))
(show-all)
(if (get-buffer “*Go Reformat Errors*”)
(progn
(delete-windows-on “*Go Reformat Errors*”)
(kill-buffer “*Go Reformat Errors*”)))
(setq max-mini-window-height 1)
(if (= 0 (shell-command-on-region (point-min) (point-max) “gofmt” “*Go Reformat Output*” nil “*Go Reformat Errors*” t))
(progn
(erase-buffer)
(insert-buffer-substring “*Go Reformat Output*”)
(goto-char (point-min))
(forward-line (1- p)))
(with-current-buffer “*Go Reformat Errors*”
(progn
(goto-char (point-min))
(while (re-search-forward “” nil t)
(replace-match filename))
(goto-char (point-min))
(compilation-mode))))
(setq max-mini-window-height old-max-mini-window-height)
(delete-windows-on “*Go Reformat Output*”)
(kill-buffer “*Go Reformat Output*”))))
;; helper function
(defun go-fix-buffer ()
“run gofix on current buffer”
(interactive)
(show-all)
(shell-command-on-region (point-min) (point-max) “go tool fix -diff”))

6. 恭喜你,你现在可以体验在神器中开发Go的乐趣. 默认speedbar是关闭的,如果打开需要把 ;; (speedbar 1) 前面的注释去掉,或者也可以通过 *M-x speedbar* 手动开启。

参考:
1. Go & Emacs http://www.let.rug.nl/~kleiweg/go/go-emacs.html
2. https://github.com/border/emacs

–EOF–

Categories: Emacs, golang Tags: , , , ,

Sina微薄oauth2验证Go实现

September 4th, 2012 No comments

Sina微薄oauth2验证Go实现的方法:
格式化后的代码在: https://gist.github.com/3607494

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2012 Jiang Bian (borderj@gmail.com). All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
 
// Email: borderj@gmail.com
// Blog: http://wifihack.net/
 
// Sina WeiBo oauth2 Login, Base on goauth2 lib
package main
 
import (
	"code.google.com/p/goauth2/oauth"
	//"crypto/tls"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"text/template"
)
 
var notAuthenticatedTemplate = template.Must(template.New("").Parse(`
<html><body>
You have currently not given permissions to access your data.
<form action="/authorize" method="POST"><input type="submit" value="Ok, authorize this app with my id"/></form>
</form>
</body></html>
`))
 
var userInfoTemplate = template.Must(template.New("").Parse(`
<html><body>
Please Input Your Sina User Name:
<form action="/getuserinfo" method="POST">
<input type="input" name="userinfo" value="b0rder"/>
<input type="submit" value="Get User Info"/>
</form>
</body></html>
`))
 
// variables used during oauth protocol flow of authentication
var (
	code  = ""
	token = ""
)
 
var oauthCfg = &oauth.Config{
	ClientId:     "2168100802",
	ClientSecret: "29da9ac80a8387c52e59ec6c957d2e1b",
	AuthURL:      "https://api.weibo.com/oauth2/authorize",
	TokenURL:     "https://api.weibo.com/oauth2/access_token",
	RedirectURL:  "http://127.0.0.1:8080/oauth2callback",
	Scope:        "",
}
 
const profileInfoURL = "https://api.weibo.com/2/users/show.json"
const port = ":8080"
 
func main() {
	http.HandleFunc("/", handleRoot)
	http.HandleFunc("/authorize", handleAuthorize)
 
	http.HandleFunc("/oauth2callback", handleOAuth2Callback)
	http.HandleFunc("/getuserinfo", getUserInfo)
 
	log.Println("Listen On" + port)
	http.ListenAndServe(port, nil)
}
 
func handleRoot(w http.ResponseWriter, r *http.Request) {
	notAuthenticatedTemplate.Execute(w, nil)
}
 
// Start the authorization process
func handleAuthorize(w http.ResponseWriter, r *http.Request) {
	//Get the Google URL which shows the Authentication page to the user
	url := oauthCfg.AuthCodeURL("")
 
	log.Printf("URL: %v\n", url)
	//redirect user to that page
	http.Redirect(w, r, url, http.StatusFound)
}
 
// Function that handles the callback from the Google server
func handleOAuth2Callback(w http.ResponseWriter, r *http.Request) {
	//Get the code from the response
	code := r.FormValue("code")
 
	t := &oauth.Transport{oauth.Config: oauthCfg}
 
	// Exchange the received code for a token
	tok, _ := t.Exchange(code)
 
	{
		tokenCache := oauth.CacheFile("./request.token")
 
		err := tokenCache.PutToken(tok)
		if err != nil {
			log.Fatal("Cache write:", err)
		}
		log.Printf("Token is cached in %v\n", tokenCache)
		token = tok.AccessToken
	}
 
	/*
		// Skip TLS Verify
		t.Transport = &http.Transport{
		    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
	*/
 
	userInfoTemplate.Execute(w, nil)
 
}
 
// Get Sina User Info
func getUserInfo(w http.ResponseWriter, r *http.Request) {
	if token == "" {
		log.Println("Get Access Token Error")
		http.Redirect(w, r, "/", http.StatusFound)
		return
	}
	user := r.FormValue("userinfo")
	if strings.TrimSpace(user) == "" {
		w.Write([]byte("Please Input User Name"))
		return
	}
 
	url := fmt.Sprintf("%s?screen_name=%s&access_token=%s", profileInfoURL, user, token)
	log.Println("url: " + url)
 
	resp, err := http.Get(url)
	defer resp.Body.Close()
 
	if err != nil {
		log.Fatal("Request Error:", err)
	}
 
	body, _ := ioutil.ReadAll(resp.Body)
	w.Write(body)
}
Categories: golang Tags: , , , , ,

Go Release相关说明

September 1st, 2012 No comments

By: minux.ma # gmail.com
FROM: https://groups.google.com/group/golang-china/msg/f71b2bd13b239313

今天在邮件列表里面讨论GC相关的问题的时候,聊到了Go Release发行相关的流程,@minux 详细总结了一下,下面原文。
PS: @minux 给Go核心代码里面提交了不少代码。

Dmitriy Vyukov前一阵(5月)在搞这个,已经提交了以下改动,
http://codereview.appspot.com/6223050 faster GC mark phase
http://codereview.appspot.com/6215065 faster GC sweep phase
后来又有几个小的性能微调,其他的暂时不知道;

PS: 可能还有人不清楚,我详细说下Go release相关的事情:
1, Go 1之后取消weekly发布,理由是这样会fragment user base
至少在短期内不会恢复;想要尝鲜的直接建议使用default分支;它是足够稳定的;

2, 当积累了足够的重要的bugfixes之后,会考虑发布一个新的Go 1.0.x版本;
其特点是:cherry pick一部分default分支的commit到release分支;要求是
不引入任何API改动(新加入API都不会考虑,如果一个bugfix必须引入新API,
那么要么这个改动不被选择要么会把导出符号改成非导出符号);保证用户
可以安全升级。

这个版本的发布流程大概包括如下三歩:
(1) 在golang-dev发布一个表格指示哪些commit计划被加入新的发布;此阶段
接受意见,但是绝大多数情况下只会接受反对加入某个commit的意见;想要
加入一个新commit是要花很大精力的。
这个表格以CL的形式发布方便大家评论。
示例:http://codereview.appspot.com/6279048/ (cherry pick的过程是自动的,
这个CL里面包含所需要的所有脚本)
(2) 在golang-dev发布几个preview,但是都不打包,需要自己去clone然后测试,
面向开发者
比如这个:https://groups.google.com/d/topic/golang-dev/9UtB9iZBo4o/discussion
(3) 发布
在所有支持的系统上编译测试然后制作安装包,测试;上传到

http://code.google.com/p/go/downloads/list;然后在go-nuts发布更新说明;

关于Go 1.0.3的发布日期到现在也没有确定;而且还有标记优先级为Soon的问题
没解决,所以可能还得等等;

3,经过足够考验后的default分支在合适的时候用来发布Go 1.1
所有前段时间的改变,包括新添加的API会在这个时候发布出来。
也就是这次会是个merge。据说是今年年底发布这个。
-EOF-

Categories: golang Tags: , ,

用Go写了个取得Youtube下载地址和字幕地址

March 12th, 2012 No comments

用Go正则写了个取得Youtube下载地址和字幕地址具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main
 
import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"
)
 
func main() {
	c := new(http.Client)
	//resp, err := c.Get("http://www.youtube.com/watch?v=OOUD2j-l7BI&feature=g-u-u&context=G2c38d77FUAAAAAAACAA")
	resp, err := c.Get("http://127.0.0.1/youtube.htm")
 
	if err != nil {
		fmt.Println("Error: ", err)
		return
	}
	defer resp.Body.Close()
	buf, err := ioutil.ReadAll(resp.Body)
 
	beginRegStr := `(?Usmi)yt.playerConfig.=.{.*"args":.{"ttsurl":."(.*)",.*"url_encoded_fmt_stream_map":."(.*)",.*}.*};`
 
	beginRegex, _ := regexp.Compile(beginRegStr)
 
	pos := beginRegex.FindAllSubmatch(buf, 1024)
	if pos == nil {
		fmt.Println("Nothing matched!")
		return
	}
 
	subtitle := make([]byte, 1024)
	urlsArray := make([]byte, 1024*20)
 
	for i := 0; i < len(pos); i++ {
		subtitle = pos[i][1]
		urlsArray = pos[i][2]
	}
	fmt.Println("subtitle: ", string(subtitle))
 
	urlStr := strings.Split(string(urlsArray), ",")
	for i := 0; i < len(urlStr); i++ {
		fmt.Println(i, ", ", urlStr[i])
	}
}

格式化后的代码: https://gist.github.com/2016902

Categories: golang Tags: , , , ,

招商证券股票day数据格式分析

January 8th, 2012 No comments

今天没事想把招商证券保存的股票数据提取出来, 后来发现招商证券的软件是采用是通达信做的, 这样直接通过查找通达信的数据格式就搞定了.

主要参考: http://alantop.5166.info/gpdatasoft/gpformat/gpformat.htm#_Toc224993378

通达信日线

每条数据文件占32个字节。每四个字节代表一个变量。如下所示:

 

1
2
3
4
5
6
7
8
9
10
11
struct stockDay
{
uint32_t date; //日期
uint32_t open; //开盘价,单位:分
uint32_t high; //最高价,单位:分
uint32_t low; //最低价,单位:分
uint32_t close; //收盘价,单位:分
float amount; //交易金额,单位:元
uint32_t vol; //成交量,单位:股
int32_t reserv; //保留,有时用来保存上一交易日收盘价
};

我分别使用C和Go写了个简单的提取程序.

C代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdint.h&gt;
#include &lt;string.h&gt;
struct stockDay
{
uint32_t date; //日期
uint32_t open; //开盘价,单位:分
uint32_t high; //最高价,单位:分
uint32_t low; //最低价,单位:分
uint32_t close; //收盘价,单位:分
float amount; //交易金额,单位:元
uint32_t vol; //成交量,单位:股
int32_t reserv; //保留,有时用来保存上一交易日收盘价
};
 
void printDay(struct stockDay *day)
{
printf("日期: %d, ", day-&gt;date);
printf("开盘价: %.2f, 最高价: %.2f, 最低价: %.2f, 收盘价: %.2f, ", day-&gt;open/100.0, day-&gt;high/100.0, day-&gt;low/100.0, day-&gt;close/100.0);
printf("交易金额: %f, 交易量: %d\n", day-&gt;amount, day-&gt;vol);
}
 
int main()
{
FILE *p;
int i = 0;
char *file = "./sh600529.day";
struct stockDay *day = malloc(sizeof(struct stockDay));
 
p = fopen(file, "r");
if (p) {
fseek(p, 0, SEEK_END);
uint64_t iFileLen = ftell(p)/(sizeof(struct stockDay));
rewind(p);
for (i = 0; i &lt; iFileLen; i++) {
memset(day, 0, sizeof(struct stockDay));
fread(day, sizeof(struct stockDay), 1, p);
printDay(day);
}
 
} else {
printf("Read File: %s Error!\n", file);
}
 
free(day);
fclose(p);
return 0;
}
Go的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package main
 
import (
"bytes"
"encoding/binary"
"fmt"
"io/ioutil"
"unsafe"
)
 
type StockDay struct {
date uint32 //日期
open uint32 //开盘价,单位:分
high uint32 //最高价,单位:分
low uint32 //最低价,单位:分
cls uint32 //收盘价,单位:分
amount float32 //交易金额,单位:元
vol uint32 //成交量,单位:股
reserv int32 //保留,有时用来保存上一交易日收盘价
}
 
func main() {
contents, _ := ioutil.ReadFile("./sh887001.day")
//println(string(contents));
var day StockDay
size := int(unsafe.Sizeof(day))
fmt.Printf("sizeof: %d, days: %d\n", size, len(contents)/size)
for i := 0; i &lt; len(contents); i += 32 {
buf := bytes.NewBuffer(contents[i : i+4])
err := binary.Read(buf, binary.LittleEndian, &amp;day.date)
if err != nil {
fmt.Println("binary.Read failed: ", err)
}
buf = bytes.NewBuffer(contents[i+4 : i+8])
err = binary.Read(buf, binary.LittleEndian, &amp;day.open)
 
buf = bytes.NewBuffer(contents[i+8 : i+12])
err = binary.Read(buf, binary.LittleEndian, &amp;day.high)
 
buf = bytes.NewBuffer(contents[i+12 : i+16])
err = binary.Read(buf, binary.LittleEndian, &amp;day.low)
 
buf = bytes.NewBuffer(contents[i+16 : i+20])
err = binary.Read(buf, binary.LittleEndian, &amp;day.cls)
 
buf = bytes.NewBuffer(contents[i+20 : i+24])
err = binary.Read(buf, binary.LittleEndian, &amp;day.amount)
 
buf = bytes.NewBuffer(contents[i+24 : i+28])
err = binary.Read(buf, binary.LittleEndian, &amp;day.vol)
 
fmt.Printf("%v\n", day)
}
}

 

代码也贴在Github上: https://gist.github.com/1578661

ps: 目前5分钟线的月份和日期对不上, 不知道哪位高手搞过?

–EOF–