- パッケージ内に定義した関数を外部に公開するにはどうすれば良いか?
- 非同期に処理を行う為の命令は?
- 関数を抜けた際に処理を実行するにはどうするか?
- goroutineの同時実行数を変更するにはどうするか?
- コンパイラやリンカが8g/6g/5g、8l/6l/5lという名前になっている理由は?
- Goのガベージコレクションの実装は一般的に何と呼ばれている類か?
- レシーバがnilの場合にメソッドを呼び出すと何が起きるか?
- 可変個引数はどの様に定義するか?
- 関数内で定義されるローカル変数のアドレスを戻り値として外部から参照するとどうなるか?
- interfaceとstructの違いは何か?
- panicを補足して強制終了させない為にはどうするか?
2011/03/08
Goプログラマであるかを見分ける10の質問
下記質問にそれぞれ50文字以内を目安に簡単に説明すること。
2011/03/06
go-gtkがWindowsで動いた。
この時をずっとまってた。
Google製の新しいコンパイル型言語Go上で動くGTK GUIライブラリ、go-gtkが今日、windowsで動いた。
Xming上で動いている様にも見えますが、ちゃんとwin32 nativeなGTKで動いてます。
まずは一般的なGUIのサンプル。
だいたい動きました。ここ数日、cgoのwin32対応に関するsubmitが多くなってたので、そろそろ動くかなと思って着手しました。win32向けに対応した部分としては実はそんなに多くないです。go-gtkはイベントポーリングを自前でやっていて、その排他制御にpthreadを使っているんですが、win32だとpthread_mutex_lock/pthread_mutex_unlockでうまく排他制御出来なかった(gdkのスレッドと相性が良くないのか落ちる)ので、win32ではクリティカルセクションを使う様にお得意の#ifdefで修正しました。
gtksourceviewの一部で落ちるのを1件確認してますが、その他はほぼ動きました。
GUIが扱えるスクリプト言語は数ありますが、nativeにコンパイル出来てオブジェクト思考で、非同期(goroutine)が使えるGoでGUIライブラリがwindows上で動いたのは、正直大きいと個人的には思っています。
Goの高速なコンパイルと、Duck Typingによる自由度の高い型変換により脳内で設計した物が思考停止する事なくアウトプット出来るのです。
同じコードで比べないと比較になりませんが、C言語でcurlとgtkを使ってtwitterのpublic timelineをGUI表示(アイコン表示あり)というコードがあったとして、僕のノートPC(Intel Core i5)ではコンパイル/リンクがだいたい5秒程度くらいかかりますが、go-gtkの同等サンプルexample/twitterだと2秒くらいでビルド出来ます。
これからGoでGUIを使ったアプリケーションを作りたいという方にはぜひ試して欲しいと思います。
Goがwindowsで動き出してまだホヤホヤですが、これから普及していく事を望んでます。
Google製の新しいコンパイル型言語Go上で動くGTK GUIライブラリ、go-gtkが今日、windowsで動いた。
Xming上で動いている様にも見えますが、ちゃんとwin32 nativeなGTKで動いてます。
まずは一般的なGUIのサンプル。
そしてgoroutineで非同期にtwitter public timeline(非streaming API)を読み込むサンプル。
だいたい動きました。ここ数日、cgoのwin32対応に関するsubmitが多くなってたので、そろそろ動くかなと思って着手しました。win32向けに対応した部分としては実はそんなに多くないです。go-gtkはイベントポーリングを自前でやっていて、その排他制御にpthreadを使っているんですが、win32だとpthread_mutex_lock/pthread_mutex_unlockでうまく排他制御出来なかった(gdkのスレッドと相性が良くないのか落ちる)ので、win32ではクリティカルセクションを使う様に
gtksourceviewの一部で落ちるのを1件確認してますが、その他はほぼ動きました。
GUIが扱えるスクリプト言語は数ありますが、nativeにコンパイル出来てオブジェクト思考で、非同期(goroutine)が使えるGoでGUIライブラリがwindows上で動いたのは、正直大きいと個人的には思っています。
Goの高速なコンパイルと、Duck Typingによる自由度の高い型変換により脳内で設計した物が思考停止する事なくアウトプット出来るのです。
同じコードで比べないと比較になりませんが、C言語でcurlとgtkを使ってtwitterのpublic timelineをGUI表示(アイコン表示あり)というコードがあったとして、僕のノートPC(Intel Core i5)ではコンパイル/リンクがだいたい5秒程度くらいかかりますが、go-gtkの同等サンプルexample/twitterだと2秒くらいでビルド出来ます。
これからGoでGUIを使ったアプリケーションを作りたいという方にはぜひ試して欲しいと思います。
Goがwindowsで動き出してまだホヤホヤですが、これから普及していく事を望んでます。
2011/02/24
Goでblosxomライクなブログサーバ書いた。
新しい言語を始めて慣れてくると、必ず作りたくなるのがblosxomですね。(ですよね?)
て事でGoでblosxomライクなのを作った。cgiも出来なくないけど、GoはWebに強かったりもするので、web.goを使ってサーバとして書いた。
名前は「blogo」(ブロゴー!えっ)。blosxomライクにテキストファイルを読み込んで、タイトルと本文をこしらえます。
今回はHTMLのテンプレートエンジンとしてmustache(マツタケじゃないよ)を選びました。
結構ハマってしまったけど、一通り動いた。設定ファイル(JSON)でフォルダ位置やタイトル、サブタイトル、リンク一覧なんかを変更出来ます。見た目はこんな感じ。
て事でGoでblosxomライクなのを作った。cgiも出来なくないけど、GoはWebに強かったりもするので、web.goを使ってサーバとして書いた。
名前は「blogo」(ブロゴー!えっ)。blosxomライクにテキストファイルを読み込んで、タイトルと本文をこしらえます。
今回はHTMLのテンプレートエンジンとしてmustache(マツタケじゃないよ)を選びました。
結構ハマってしまったけど、一通り動いた。設定ファイル(JSON)でフォルダ位置やタイトル、サブタイトル、リンク一覧なんかを変更出来ます。見た目はこんな感じ。
短いのでソース全部のっける。
package main
import "bytes"
import "html"
import "io"
import "io/ioutil"
import "mustache"
import "os"
import pathutil "path"
import "regexp"
import "strings"
import "time"
import "web"
import "json"
type Tag struct {
Name string
}
type Entry struct {
Id string
Filename string
Title string
Body string
Created *time.Time
Category string
Author string
Tags []Tag
}
func toTextChild(w io.Writer, n *html.Node) os.Error {
switch n.Type {
case html.ErrorNode:
return os.NewError("unexpected ErrorNode")
case html.DocumentNode:
return os.NewError("unexpected DocumentNode")
case html.ElementNode:
case html.TextNode:
w.Write([]byte(n.Data))
case html.CommentNode:
return os.NewError("COMMENT")
default:
return os.NewError("unknown node type")
}
for _, c := range n.Child {
if err := toTextChild(w, c); err != nil {
return err
}
}
return nil
}
func toText(n *html.Node) (string, os.Error) {
if n == nil || len(n.Child) == 0 {
return "", nil
}
b := bytes.NewBuffer(nil)
for _, child := range n.Child {
if err := toTextChild(b, child); err != nil {
return "", err
}
}
return b.String(), nil
}
func GetEntry(filename string) (entry *Entry, err os.Error) {
fi, err := os.Stat(filename)
if err != nil {
return nil, err
}
f, err := os.Open(filename, os.O_RDONLY, 0)
if err != nil {
return nil, err
}
b, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}
in_body := false
re, err := regexp.Compile("^meta-([a-zA-Z]+):[:space:]*(.*)$")
if err != nil {
return nil, err
}
for n, line := range strings.Split(string(b), "\n", -1) {
line = strings.TrimSpace(line)
if n == 0 {
entry = new(Entry)
entry.Title = line
entry.Filename = pathutil.Clean(filename)
entry.Tags = []Tag{}
entry.Created = time.SecondsToUTC(fi.Ctime_ns / 1e9)
continue
}
if n > 0 && len(line) == 0 {
in_body = true
continue
}
if in_body == false && re.MatchString(line) {
submatch := re.FindStringSubmatch(line)
if submatch[1] == "tags" {
tags := strings.Split(submatch[2], ",", -1)
entry.Tags = make([]Tag, len(tags))
for i, t := range tags {
entry.Tags[i].Name = strings.TrimSpace(t)
}
}
if submatch[1] == "author" {
entry.Author = submatch[2]
}
} else {
entry.Body += strings.Trim(line, "\r") + "\n"
}
}
if entry == nil {
err = os.NewError("invalid entry file")
}
return
}
type Entries []*Entry
func (p *Entries) VisitDir(path string, f *os.FileInfo) bool { return true }
func (p *Entries) VisitFile(path string, f *os.FileInfo) {
if strings.ToLower(pathutil.Ext(path)) != ".txt" {
return
}
if entry, err := GetEntry(path); err == nil {
*p = append(*p, entry)
}
}
func GetEntries(path string, useSummary bool) (entries *Entries, err os.Error) {
entries = new(Entries)
e := make(chan os.Error)
pathutil.Walk(path, entries, e)
for _, entry := range *entries {
if useSummary {
doc, err := html.Parse(strings.NewReader(entry.Body))
if err == nil {
if text, err := toText(doc); err == nil {
if len(text) > 500 {
text = text[0:500] + "..."
}
entry.Body = text
}
}
}
entry.Id = entry.Filename[len(path):len(entry.Filename)-3] + "html"
}
if len(*entries) == 0 {
entries = nil
}
return
}
type Config map[string]interface{}
func (c *Config) Set(key string, val interface{}) {
(*c)[key] = val
}
func (c *Config) Get(key string) string {
val, ok := (*c)[key].(string)
if !ok {
return ""
}
return val
}
func LoadConfig() (config *Config) {
root, _ := pathutil.Split(pathutil.Clean(os.Args[0]))
b, err := ioutil.ReadFile(pathutil.Join(root, "config.json"))
if err != nil {
println(err.String())
return &Config{}
}
err = json.Unmarshal(b, &config)
return
}
func main() {
config := LoadConfig()
web.Get("/(.*)", func(ctx *web.Context, path string) {
config = LoadConfig()
datadir := config.Get("datadir")
if path == "" || path[len(path)-1] == '/' {
dir := pathutil.Join(datadir, path)
stat, err := os.Stat(dir)
if err != nil || !stat.IsDirectory() {
ctx.NotFound("File Not Found")
return
}
var useSummary = false
if config.Get("useSummary") != "" {
useSummary = true
}
entries, err := GetEntries(dir, useSummary)
if err == nil {
ctx.WriteString(mustache.RenderFile("entries.mustache",
map[string]interface{}{
"config": config,
"entries": entries}))
return
}
} else if len(path) > 5 && path[len(path)-5:] == ".html" {
file := pathutil.Join(datadir, path[:len(path)-5] + ".txt")
_, err := os.Stat(file)
if err != nil {
ctx.NotFound("File Not Found")
return
}
entry, err := GetEntry(file)
if err == nil {
ctx.WriteString(mustache.RenderFile("entry.mustache",
map[string]interface{}{
"config": config,
"entry": entry}))
return
}
}
ctx.Abort(500, "Server Error")
})
web.Config.RecoverPanic = false
web.Config.StaticDir = config.Get("staticdir")
web.Run(config.Get("host"))
}
それと、今回初めてCSS FrameworkであるBlueprintを使った。まぁ確かに慣れてると使いやすいのかもしれないけど、CSSそんなに知らない人が使い始められる物じゃないなと思った。Goのコード書くよりこのレイアウト作る方に時間がかかったという...mattn/blogo - GitHub
blogo : blosxom like blog engine for golang
http://github.com/mattn/blogo