Skip to main content

8 posts tagged with "golang"

View All Tags

· 2 min read

Golangで []T を []interface{} に変換しなければならないのだろうか?という疑問があった。

具体的には次のようなコードの場合。

▶The Go Playground http://play.golang.org/p/Gg2NTEQFBX

package main

import "fmt"

func main() {
fmt.Println("Hello, playground")
A("a", "b", "c", "d", "e") // [a b c d e] ... Not the expected value.
AA("a", "b", "c", "d", "e") // OK ... the expected value.
}

func A(text ...string) {
// B(text...) // prog.go:12: cannot use text (type []string) as type []interface {} in argument to B
B(text)
}

func AA(text ...string) {
ss := make([]interface{}, len(text))
for i, s := range text {
ss[i] = s
}
B(ss...)
}

func B(values ...interface{}) {
for _, value := range values {
fmt.Println(value)
}
}

Aメソッドに可変長引数を渡した場合、さらに別のメソッドの引数がinterface{}の可変長引数ならそのままいけるかな?と思ったらいけなかった。
AAメソッドのように詰め直してあげれば問題ないことはわかっているんだけど、もっとシンプルにスマートな方法ってないのだろうか?という疑問があった。

調べてみるとこんなところにまんま載っていた!

▶Frequently Asked Questions (FAQ) - The Go Programming Language
https://golang.org/doc/faq#convert_slice_of_interface

Can I convert a []T to an []interface{}?

Not directly, because they do not have the same representation in memory. It is necessary to copy the elements individually to the destination slice. This example converts a slice of int to a slice of interface{}:

t := []int{1, 2, 3, 4}
s := make([]interface{}, len(t))
for i, v := range t {
s[i] = v
}

やっぱり、こうしろということらしい。

· 3 min read

Google App Engine/Goを実装するときは次のようにするのがよい。

  • GOPATHをひとつにする
  • コードはsrc配下
  • importはフルパス
  • app.go, app.yamlはsrc直下

前提​

goコマンドの代わりにgoappコマンドを使う。

▶Google Cloud SDK — Google Cloud Platform
https://cloud.google.com/sdk/

GOPATHをひとつにする​

デプロイ時に関連ファイルを含める必要があるため。

コードはsrc配下​

自分の書いたコードはsrcディレクトリ配下に置く。
goapp getしたファイルも自分が書いたコードもsrc配下にまとまっているということになる。

importはフルパス​

import文はフルパスで書く。
GOPATHはひとつにまとめているし、これで困ることはない。
それと、goapp testしたときにもうまく解決される。

app.go, app.yamlはsrc直下​

app.goとapp.yamlはsrcディレクトリに保存する。

src
├── app.go
├── app.yaml
├── myproject
├── github.com
└── code.google.com

まとめ​

この構成にする前はapp.goとapp.yamlをmyprojectの下に置いていたのでうまく動かなかった。
App Engineで動かしたいものはmyprojectだし…と思っていたのだが、app.goから見たらmyprojectも複数プロジェクトのうちのひとつでしかないということで納得。

もう少し丁寧に書いておきたいけど、忘れないうちに構成だけメモ。

このツイートの返信でいろいろと教えてくださった @mattn_jp さんに感謝!!

▶GAE/Go でのGOPATH設定 - The Round
http://knightso.hateblo.jp/entry/2014/11/26/103637
ここの構成と違うからちょっと気になる…もう少し確認した方がいいかもしれない。

· One min read

またGoで半ばはまりかけた。

JSONを構造体に変換する際に「データの中身を確認したいなぁ」とReadAllすると、res.Bodyの中身が空っぽになる。

// 次の行をコメントアウトすれば期待通りにJSONが構造体に変換される。
body, _ := ioutil.ReadAll(res.Body)

data := &Data{}
json.NewDecoder(res.Body).Decode(data)

· One min read

Go言語でJSONをStructに変換する際のポイント。

type User struct {
Id string `json:"id"`
FirstName string `json:"first_name"` // OK
// FirstName string `json: "first_name"` // NG :の後ろに空白がある。
// FirstName string `json:first_name` // NG スネークケースが""で括られてない
}

これはハマる!!

· 2 min read

昨日のレシーバによる挙動の違いがとりあえず解決した。 解決というより、挙動がわかっていたからそれを使って実装したというだけであって、なんだこれ?って気がしないでもない。

なんだこれって思う部分はA構造体のSelfフィールドって、型は違えど同じAインスタンスというところ。

http://play.golang.org/p/cJOGzaLhKm
package main

import (
"fmt"
"reflect"
)

type I interface {
Call()
Method(interface{})
SetSelf(I)
}

type A struct {
Self I
a1 bool
}

func (a *A) Call() {
a.Self.Method(a.Self)
}
func (a *A) SetSelf(i I) {
a.Self = i
}

func (a *A) Method(i interface{}) {
ip := reflect.ValueOf(i)
iv := ip.Elem()
fmt.Println("name:", iv.Type().Name())
for ii := 0; ii < iv.NumField(); ii++ {
fmt.Println(iv.Field(ii))
}
}

type B struct {
A
b1 int
b2 float32
b3 bool
}

func main() {
var bi interface{}
bi = &B{}
t := reflect.TypeOf(bi).Elem()
b := reflect.New(t)
i, _ := b.Interface().(I)
i.SetSelf(i)

fmt.Println("----- invoke 'Method' via 'Call'. -----")
i.Call()
fmt.Println("----- invoke direct 'Method'. -----")
i.Method(i)
}

/*
----- invoke 'Method' via 'Call'. -----
name: B
<main.A Value>
<int Value>
<float32 Value>
<bool Value>
----- invoke direct 'Method'. -----
name: B
<main.A Value>
<int Value>
<float32 Value>
<bool Value>
*/

· 2 min read

ある構造体のフィールドを得ようと実装したら、なぜか継承元(Goではこう言わないか)のフィールドしか取得できなかった。 構造体を引数に実行すれば取得できるけど、同じメソッドを呼んでいるのだが…。

これはどう理解したらいいのかわからない。

http://play.golang.org/p/KcfBp2myhR
package main

import (
"fmt"
"reflect"
)

type I interface {
Call()
Method(interface{})
}

type A struct {
a1 bool
}

func (a *A) Call() {
a.Method(a)
}

func (a *A) Method(i interface{}) {
ip := reflect.ValueOf(i)
iv := ip.Elem()
fmt.Println("name:", iv.Type().Name())
for ii := 0; ii < iv.NumField(); ii++ {
fmt.Println(iv.Field(ii))
}
}


type B struct {
A
b1 int
b2 float32
b3 bool
}

func main() {
var bi interface{}
bi = &B{}
t := reflect.TypeOf(bi).Elem()
b := reflect.New(t)
i, _ := b.Interface().(I)

fmt.Println("----- invoke 'Method' via 'Call'. -----")
i.Call()
fmt.Println("----- invoke direct 'Method'. -----")
i.Method(i)
}

/*
----- invoke 'Method' via 'Call'. -----
name: A
&lt;bool Value&gt;
----- invoke direct 'Method'. -----
name: B
&lt;main.A Value&gt;
&lt;int Value&gt;
&lt;float32 Value&gt;
&lt;bool Value&gt;
*/

· 5 min read

バリデーションをわかりやすく実装するって難しいって話。 頭の中を整理するために書いているので、まとまってない状態。

基本的なお話

ログイン時にIDとパスワードをポストするけど、受け取った側としてはその値が正しいかどうかを判断する。 この "正しいかどうかを判断する" ってのがやっかい。 IDとして正しいかどうか?というのは、

  • 英数字だけか?
  • 8文字以上か?

のような感じではあるが、これって 値が存在する前提の話 なんだよね。 まずは値が存在しているのかどうか?ってところから判断して、存在しない場合は正しいかどうかって判断できない。 だから、

  • 値が存在するか?

ってのも確認しなければならない。

悩み

どうやって実装したら綺麗なのか?

if id, ok := param("id"); ok {
id.validation(required, max(8))
}

これでもいいんだけど、前提条件が揃っているか(パスワードが送られてきているか)を確認してから処理に移りたいよねって思う。

if (required("id", "password")) {
id := param("id")
pw := param("password")
}

そうなるとこんな感じかな?

だけど、他にもIDを保存しておくか?的なオプションがあって、keepidなんて項目まであったとする。

if (required("id", "password")) {
id := param("id")
pw := param("password")
if keep, ok := param("keep"); ok && len(keep) != 0 {
// IDを覚えておく処理
}
}

なんてのはすっきりしないなぁ…と。 だいたい、値が送られて来なくても、値が空文字列であっても『IDは必要だよ』って旨は表示するわけだし、この辺が実装と現実の乖離。

さらに 値がない場合は初期値としてこれを使いたい みたいな場合は厄介事が増えてしまう。

こういうを考えているとScalaのOptionとmatchの表現はすっきりでいいなぁ…と思えてしまう。

こういうときはGoではどう書けばすっきりするんだ?

まとめ

値の存在確認もバリデーションって言葉で片付けられることあるけど、その言葉には依存関係が存在することもあって、スマートな解決を求める場合は一言で表さない方がいいのでは?と思ったりした。 今回の場合は、

  • 存在確認
  • 各種バリデーション

なのかな?と。全部まとめてバリデーションって表現もいいけど、実装上はこの差を明確にしておいた方がわかりやすいんじゃないかなと思った。 だけど、必ず存在していないと困るか?というとそういう項目ばかりではなくて…。

フレームワークって色々とやってくれるから便利ってのはもちろんのこと、この辺をあまり悩まなくて済むというのも大きなメリットだよな、と思ったのであった。

# コードハイライトの指定に "Go" がなくて "Python" にしちゃったよ。

· 2 min read

Goは色々と今までの言語と異なり、慣れるのに一苦労なんじゃないか?と思いつつも、コンセプトは結構好き。 そんな言語だけど、こういう初歩的なところで悩むことが多い。

go func

さぁ、どっちがいいのか?

無名関数として実行している。

i := 3
var result int
func() {
result = i * 10
}()

goroutineとして実行している。

i := 3
c := make(chan int)
var result int
go func() {
result = i * 10
c<- 1
}()
<-c

どっちがいいというか、こういう書き方ができるというサンプルであって、

  • 処理を明示したいなら前者
  • そっちの処理をさせつつ、そのまま別の処理もしたい場合は後者

って使い分けなのかなぁ?と思っている。

前者はこうすべきなのでは?と思ったり。

i := 3
result := func() (result int) {
result = i * 10
return
}()

まとめ

こういう作法とか使い分けを知りたい。