ぷらこのきろく

メモとかテストとか備忘録とか

構造体とポインタの話

まあ、あたりまえっちゃあたりまえなんだろうけど、一応確かめておこうと思ったこと。

package main

import "fmt"

type hoge struct {
	a int
	b float64
	s string
}

構造体を適当に宣言しておく。

func main() {
	var h *hoge
	h = new(hoge)

	h.a = 5
	h.b = 3.14
	h.s = "hogehoge"

	fmt.Println(h.a,",",h.b,",",h.s)
}

このコードは、ちゃんと動く。
でも、

	h = new(hoge)

この一行を書かないと、コンパイルは通るけど実行時エラーが出て動かない。
ポインタ型を宣言してるけど、構造体の中身を確保していないから当然だろう。

で、main()関数の最初の二行を

	h: = &hoge{}

とすると、動く。当然だといわれればそうなんだけど、構造体の確保って、Cでいう静的とか動的とか意識したら、どっちがいいんだろうと思ったりしたりするのかなぁ。と。

まあ、あんまり深く考えなくていいのかもしれないけど。。


ちょっとコードを書き足して、

func (h *hoge)print() {
	fmt.Println(h.a,",",h.b,",",h.s)
}

こんなのを書いてみて、main()関数の終わりの方で

	h.print()

って呼び出してみた。
やっぱり、var h *hogeだけでは動かないみたいでh=new(hoge)がいるようだし、
h:=&hoge{}
だったらちゃんと動いた。

よく考えたら当然なんだけど、実際手で納得してみたので日記行き。

walk PushButton

今日遊んだコードはこんな感じ

package main

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)
import (
	"strings"
)

func main() {
	var te1  *walk.TextEdit
	
	MainWindow{
		Title: "hello",
		Size: Size{320, 480},
		Layout: VBox{},
		Children: []Widget {
			TextEdit {
				AssignTo: &te1,
			},
			PushButton{
				Text: "hello",
				ToolTipText: `put "hello"`,
				OnClicked: func() {
					text := te1.Text()
					text = strings.Join(
						[]string{text, "hello"},
						"")
					te1.SetText(text)
				},
			},
		},
	}.Run()
}

TextEditのところまでは昨日(だっけ)のとほぼ同じ。PushButtonをとりあえず使ってみた。

Textの部分は、ボタンに書かれる文字列が入る。
中身を見てみると、Property型となってて、さらに見てみると、interface{}型だった。つまり、どんな型の中身を入れても理論上問題はないみたい。実際にint型の123を入れてみたが、コンパイルは通った。
ただ、string型でないと実行時にエラーが起きた。結局string型しか入らないんだろう。なんでそんな仕様になってるかまだわからないけど、とりあえずそんな感じ。

ToolTipTextは、ここに文字列いれておくと、マウスカーソルを合わせたときに説明が出る。

OnClickedは、関数が入る。ボタン押されたときに処理をしてくれる。
中身はwalk.EventHandler型となってるけど、さらに中身を見たらfunc()ってなってたのできっとそうなんだろう。
引数はとれないと思う。だから、データを受け渡しするには、グローバル変数を使うか、今回のコードのようにfunc()を直書きするか、ここでやってるように構造体を作ってそれで処理するか、だと思う。

walk.TextEdit型のメソッドにText()や、SetText()がある。
Text()は、中に書かれているテキストがstring型で返る。
SetText(value string)は、valueの文字列をテキストエリアに表示させる。
他のメソッドもいっぱいあるみたいだけど、それはwalk/textedit.goに書いてあるみたい。

今日はこれだけで満足。
今度はイメージ表示とかできたらいいなぁ。。

構造体

golangの構造体の中に、他の構造体の宣言を入れられるみたい。
うまいこと説明できないけど

type hogebase struct {
	j     int
}

とりあえず先に(後でもいいけど)取り込む構造体を宣言してみる。

type hoge struct {
	hogebase
	i  int
	str string
}

で、こんな感じに、先に宣言したhogebaseを中に入れておくと

func main() {	
	nanka := hoge {
		str: "string",
	}
	nanka.j = 5 //<---
}	

あたかもjがnankaのメンバ変数になってるかのように扱うことができるみたい。

ただ、

	nanka := hoge {
		str: "string",
		j:   5  // <---
	}

これはコンパイルエラーになるみたい。初期化はできない、ということだろうか。

たぶんどこかに書いてあるだろうけど、へぇって思ったので日記行き。

walk Layout

今回遊んだコードはこれがベース。昨日(だったけ)作ったコードから少しだけ変えた。

package main

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

func main() {
	var te1, te2  *walk.TextEdit
	
	MainWindow{
		Title: "hello",
		Size: Size{320, 240},
		Layout: HBox{},
		Children: []Widget {
			TextEdit {
				AssignTo: &te1,
			},
			TextEdit {
				AssignTo: &te2,
			},
		},
	}.Run()
}

Layoutというのはインターフェイス型で、それを満たす構造体にHBoxとVBoxと、Gridというのがあるみたい。
どれも

type HBox struct {
	Margins     Margins
	Spacing     int
	MarginsZero bool
	SpacingZero bool
}

という感じになってるみたいなんだけど、とりあえずはこの中身をいじるのはまた今度。
Gridはおいといて、'V'と'H'はVertical(垂直)とHorizontal(水平)の略であるのは想像に難くない。

前の日記に書き忘れたが、manifestファイルというのを書かないといけないみたい。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
	<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeFunkyNameHere" type="win32"/>
	<dependency>
		<dependentAssembly>
			<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
		</dependentAssembly>
	</dependency>
</assembly>

これをtestwalk.exe.manifestという名前で保存する。
どうも使い回しができるっぽいので、(実行ファイル名).manifestという名前でコピーして使ってる。

まあとりあえず、動かした結果がこれ。
f:id:prizeout:20130918001808j:plain
テキストボックスが二つ横に並んでる。

そして

		Layout: VBox{},

と書き換えると
f:id:prizeout:20130918002220j:plain
こんな感じになる。予想どおりVerticalとHorizontalだった。

Gridは試してみたら実行時エラーで動かなかったので、違う使い方かもしれない。

Childrenは、Widget型のスライスで、まあWidget型がいくつか並んでいるみたい。
そしてWidget型はインターフェイスで、とにかくたくさんの型が入るみたい。
今回使ったTextEdit型の構造体とか、今度使う予定のPushButton型とか、いろいろ。
とりあえずdeclarativeの下で

grep Widgetinfo *.go | grep func | less

とかしたらいっぱいでてきたので、まあそれくらいいっぱい型があるんだろう。

今日はこれぐらいで許してもらって、次はボタンを押してなんかできるようになるのが目標。

walk初め

walkを使おうとぐうぐる先生に聞いてみたが、
ここここしか見つからなかった。
それらの書いてあることはきっと初歩的なことなんだろうけど、今の僕にはまだむずかしい。
僕はまずhello worldが書きたい。

というわけで、よくわからんまま

package main

import (
//	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

func main() {
	
	MainWindow{
		Title: "hello",
		MinSize: Size{320, 240},
		MaxSize: Size{800, 600},
		Size: Size{640, 480},
	}.Run()
}

これだけ書いて動くかどうか試してみる。
f:id:prizeout:20130917024533j:plain
一応動いた。
ただ、MinSizeはちゃんとなって、それ以上ウインドウが小さくならないようになるんだけど、MaxSizeはうまく機能しない。なんでだろう。

あとの部分は、declarative/mainwindow.goにいろいろいっぱい書いてあるので、それをひとつずつ見ながら遊んでみるのかな。

skkのインストール

やっぱりskkは入れないとね、と、入れてみた。

ここからskk本体をダウンロードして解凍。なんかddskk-20130915.tar.gzという、昨日の日付のがあったのでそれを入れてみた。毎日開発されてる開発バージョンなのかな?
ここからSKK-JISYO.L をダウンロードして解凍。skkを展開したところのdicというディレクトリにコピー。
makeit.batを編集。

set PREFIX=
set EMACS=
set LISPDIR=
set DEFAULT_MAKE_ARG=

という部分があるので、そこを適当に埋める。僕の場合

set PREFIX=C:\Users\prizeout\bin\emacs
set EMACS=C:\Users\prizeout\bin\emacs\emacs-24.3\bin/emacs.exe
set LISPDIR=%PREFIX%\emacs-24.3\site-lisp
set DEFAULT_MAKE_ARG=

こんな感じで埋めてみた。%EMACS%のところがフルパスになってるのはそこを最初に書いたから。
そして、コマンドプロンプト

maikit.bat install

emacsを起動して、C-x C-j。うまくいったっぽい。

エディタあれこれ

プログラムを書こうとすると、何かしらエディタが必要なわけで。。メモ帳ではちょっとしんどい。

とーごーかいはつかんきょうっていうものらしい。
まず、ここからダウンロード。僕の環境はWindows 64bitなのでそれを。
で、javaをダウンロード。普通のjava(というか、ブラウザのプラグインのやつ)じゃなくて、JDKとかいうもの。ここから
eclipseを起動し、help→Install New Softwareを選択、Work withにhttp://goclipse.googlecode.com/svn/trunk/goclipse-update-site/といれてAdd。Add RepositoryにGoClipseといれてOK。
チェックボックスに印をつけ、Next→Next。使用条件のところをよく読んで(読まないけど)accept。Warningが一回でるので気にせずOK。再起動促されるのでOK。
Window→PreferenceからGoを選び、GOROOTを入力。僕の場合はC:\Users\prizeout\bin\go。GOPATHはいれなくても動いた気がするけど、あとでWalkインストールしたついでにいれた。C:\Users\prizeout\bin\go。ディレクトリ構成失敗したかも。。

オートコンプリート機能とかいうのもあるみたい。
gitをインストールして(これは前書いた。若干間インストール間違えたみたいだけど動けばもう獣)

go get -u github.com/nsf/gocode

でよかったと思う。ただこれ非常に重い。僕はいらんのでアンインストールしたいんだけど、どうするのか知らないから放置。

やっぱりemacsだよなぁと思いつつ、当時(一か月前くらい)はemacsがWindowsで動くとは知らなかったので、入れてみた。
たぶんこのへんから落としてきたと思う。解凍する。環境変数XYZZYHOMEに、インストールした(xyzzy.exeがある)ディレクトリを指定。僕の場合C:\Users\prizeout\bin\xyzzy
環境変数を有効にするためには、一度ログアウトしないといけないっぽい。いい方法ないもんか。
ここからgo-modeのファイルをとってくる。右下あたりにDownload ZIPって書いてあるのでそのへんから。解凍すると、etcとsite-lispというディレクトリがあるので、その中身をそのままxyzzyディレクトリのetcとsite-lispにコピー。
XYZZYHOMEのディレクトリに.xyzzyという名前のファイルを作成。中身に

(load-library "go-mode")
(push '("\\.go$" . go-mode) *auto-mode-alist*)

と書いておく。
xyzzyを起動し、M-X byte-compile-file →site-lisp/go-mode.lを指定。やらなくても動いたのでおまじないみたいなものか。

で、*.goというファイルを開くとgo-modeができる。ただこのgo-mode、たまにバグった感じになる。

xyzzyでだいたい不満なかったんだけど、go-modeがたまにバグるし、xmlモードを探してたら、公開をやめてしまってるっぽい。
そんなこんなでmeadowなんかなぁとか思いながら検索したら、emacsがWindowsで使えるじゃないか。
まあこっちの方が拡張機能とか充実してるだろうし、入れてみることにする。
このへんからダウンロード。zipを展開。
環境変数HOMEを設定。ここに.emacs.dというディレクトリが作成されて、設定ファイルとかが入るっぽい。僕はC:\Users\prizeout\homeにした。
ちなみに、これを設定しないと、.emacs.dはC:\Users\prizeout\AppData\Roamingにできる。別にこれでもいいんだけど。。
GOをインストールしたディレクトリのmisc/emacsのふたつのファイルを、emacsをインストールしたディレクトリのsite-lispにコピー。
.emacs.dの下にinit.elというファイルを作成。

(add-to-list 'load-path "PATH CONTAINING go-mode-load.el" t)
(require 'go-mode-load)

の二行を書く。
僕は他に

(set-language-environment "japanese")
(global-set-key "\C-h" 'backward-delete-char)
(setq inhibit-startup-message t)

とりあえずこれだけ書いてる。

まだemacsはそんなに実戦投入してるわけではない。なんだかんだでxyzzyは優秀かもしれない。

今のところこれだけ。viとかは使う予定なし。

追記

9/16 20:04ごろ追記
emacsで改行したあとTABキーを押す、というのが面倒なので、

(add-hook 'go-mode-hook 
	  '(lambda()
	     (define-key go-mode-map "\C-m" 'newline-and-indent)
))

というのを追加してみた。少し幸せになれた。