実行ファイルのディレクトリと実行時ディレクトリ

Go言語で、実行しているファイルの場所と実行時ディレクトリを取得するサンプル。

package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
)

func main() {
	// 実行ファイルの場所
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(dir)

	// 実行時ディレクトリ
	current, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(current)
}

Goサンプル的なライブラリ 追加

https://github.com/iwot/go-util

Goサンプル的なライブラリにHttpRouterを追加しました。
使用例を https://github.com/iwot/go-util/tree/master/example/httprouter に置いてます。

package main

import (
  "./app/articles"
  "fmt"
  "github.com/iwot/go-util/util"
  "html"
  "net/http"
  "os"
)

func main() {

    basePath := "/articles/"
    router := util.NewHttpRouter().SetBasePath(basePath)
    router.SetRoute("", articles.TopPage)
    router.SetRoute("article/<id>", articles.ArticlePage)

    // for default error
    router.SetError("default", func(message string, w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Error, %q\n", html.EscapeString(message))
    })
    // for 404 error
    router.SetError("404", func(message string, w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "404 Error, %q\n", html.EscapeString(message))
    })
    // for other error
    router.SetError("other", func(message string, w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "other Error, %q\n", html.EscapeString(message))
    })

    http.Handle(basePath, router)
    fmt.Fprint(os.Stdout, "http://localhost:8000/articles/\n")
    fmt.Fprint(os.Stdout, "http://localhost:8000/articles/article/1\n")
    err := http.ListenAndServe("localhost:8000", nil)
    if err != nil {
        panic(err)
    }
}

基礎からわかる Go言語

基礎からわかる Go言語

Goサンプル的なライブラリ

https://github.com/iwot/go-util
Goのサンプル的なライブラリをGithubで管理してます。

現在のライブラリは以下。

  • PriorityQueue(プライオリティ付きのQueue。Dijkstraのサンプルをtestに含めてます。)
  • PathMatch(URLとパスのマッチング)
  • StringBuffer
  • Stack

下二つは特に今後使用するということもないので(実装は簡単なので)、そのうち消すかも。
PriorityQueueはそのうちsort.Interfaceを継承したものに書き直すかも。

基礎からわかる Go言語

基礎からわかる Go言語

アクセスしたパスでの処理振り分け

アクセスしたパスでの処理振り分け方法に少し悩んだのでメモしておきます。

例ではhttp.Handleにはパターンとして"/app/"を登録し、ハンドラに渡されたパス("/app/post/(form|confirm|do)")をパターンマッチして処理を振り分けます。

package main

import (
    "fmt"
    "html"
    "net/http"
    "regexp"
)

type Router struct {
    config map[string]interface{}
}

func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if m, _ := regexp.MatchString(`^/app/post/form$`, r.URL.Path); m {
        fmt.Fprintf(w, "Regist Form, %q", html.EscapeString(r.URL.Path))
    } else if m, _ := regexp.MatchString(`^/app/post/confirm$`, r.URL.Path); m {
        fmt.Fprintf(w, "Regist Confirm, %q", html.EscapeString(r.URL.Path))
    } else if m, _ := regexp.MatchString(`^/app/post/do$`, r.URL.Path); m {
        fmt.Fprintf(w, "Regist Do, %q", html.EscapeString(r.URL.Path))
    } else {
        fmt.Fprintf(w, "Other, %q", html.EscapeString(r.URL.Path))
    }
}

func main() {
    http.Handle("/app/", &Router{config: make(map[string]interface{})})
    http.Handle("/", http.FileServer(http.Dir("./static")))
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        panic(err)
    }
}

これを基に簡単なフレームワークを書くか。

package http の func pathMatch の定義を見て解決したわけですが、やっぱり定義へのジャンプ機能がないとめんどくさかったろうなといった感じです。
当初はLiteIDEで調べてましたが、Sublime Text 2(GoSublime)でも同様に定義へのジャンプが可能です(ショートカットはctrl+dot,ctrl+g)。

基礎からわかる Go言語

基礎からわかる Go言語

Go言語でローカルパッケージをインポート

基礎からわかるGo言語には載っていなかったようなのでメモ。

パッケージのimportに関してよく見かける説明では、importするパッケージはGOPATH以下に配置されている必要がありますが、わざわざGOPATHにパスを追加して管理するのも面倒に感じます。
そういう場合は普通に相対パスでimportすればOKです。

以下のようなファイルがあり、

main.go
mystr/mystring.go

以下のような内容であれば実行できます。

main.go

package main

import (
	"./mystr"
	"fmt"
)

func main() {
	var message mystr.MyString = "OKOK"
	fmt.Println(message)
}

mystr/mystring.go

package mystr

type MyString string

ヘルプは以下のコマンドで見られます。

go help packages

該当箇所。

...
An import path that is a rooted path or that begins with
a . or .. element is interpreted as a file system path and
denotes the package in that directory.
...

基礎からわかる Go言語

基礎からわかる Go言語

Windows Haskell のReadlineがインストールできない

WindowsのHaskell

import System.Console.Readline

とするために

cabal install readline

としたのだけど、どうしてもエラーが出る。
readlineのヘッダファイルが読めればいいのかと思ってCygwinからやってみたけど、やっぱり駄目。

どうにかできないものかとネットをうろうろしてようやく発見。
readlineの代わりに、Windowsにも対応しているらしいHaskelineを使ってみることにしました。

ただし、プロンプトから

cabal install haskeline

としてもエラーが出てインストールできず。
エラー内容からしてどうやら文字コード関係らしかったので、Cygwinからのインストールで今度こそ完了しました。

import System.Console.Haskeline

のようにして使用できます。
詳細はこちらから。
http://hackage.haskell.org/packages/archive/haskeline/0.6.4.5/doc/html/System-Console-Haskeline.html


インストール時の文字コード関連エラーは、プロンプトからでも

set LANG=C

とすれば解決できるようですが、こちらは試してません。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!