Go言語でJSONを作成したときのイージーミス
2018/05/11
はじめに Go言語を使って構造体をJSON形式に変換しようとしたら詰まったのでメモです。 JSON形式への変換は標準パッケージに含まれているjson.Marshalを使っています。 失敗例 こんな感じで構造体のスライスをJSONにしようとしたところ、作成されたJSONの中身が空になっていました。 成功例 原因がわからなかったので色々と試行錯誤した結果、下記のコードで想定した動きを確認することができました。 失敗例では10〜12行目の構造体のフィード名の先頭文字を小文字にしていましたが、成功例では先頭文字を大文字に変えています。 原因 ここまで書けば原因がわかる方も多いと思いますが… Go言語では変数や関数のスコープが先頭文字列が小文字か、大文字かで判定されます。 先頭文字が大文字の場合は他パッケージからの参照が可能(いわゆるpublic)、先頭文字が小文字の場合は他パッケージから参照不可(いわゆるprivate)となります。 このルールは構造体のフィードにも適用されます。 そのため、失敗例では構造体のフィードに対してパッケージ外からアクセスすることができず、作成されたJSONが空っぽになっていました。 ちなみに 作成されるJSONのKeyを先頭小文字にしたい場合、以下のようにフィードに対してタグをつけることで任意の名前を指定することができます。 おわりに 初歩的なミスでしたが原因に気づくまで時間がかかってしまいました。 前に触ったことがあるはずなんですが…先頭文字でスコープが変化するのは慣れないと忘れちゃいますね。 コンパイルエラーとかで教えてくれないかなぁ。
13日の金曜日です
2017/01/13
はじめに 2017年1月13日は金曜日です。 Wikipediaをみると諸説あるようですが、主に海外では縁起の悪い日として知られています。 キリストの最後の晩餐に13人の人がいたことから、13は不吉な数とされた。また、キリストが金曜日に磔刑に処せられたとされていることから、13日の金曜日が不吉であるとされるようになった。一説には、イヴによるアダムの誘惑も大洪水からノアが脱出したのもバベルの塔が壊されたのも13日の金曜日だと言われるが、聖書にそのような記述はない。 北欧神話では12人の神が祝宴を催していた時に、13人目となる招かれざる客ロキが乱入して人気者のバルドルを殺してしまったとされ、キリスト教以前から13を不吉な数としており、13日の金曜日についても伝説を持つ。それは魔女としてキリスト教に追いやられたフリッグが11人の魔女と悪魔を招いて毎週金曜日に悪事を企んでいたからだという。なおゲルマン諸語で「金曜日」を表す語は「フリッグの日」に由来する。 フィリップ4世がフランス全土においてテンプル騎士団の壊滅を図るため、メンバーたちを一斉に逮捕したのが、1307年10月13日の金曜日だった。その後騎士団は異端とされ財産を没収の上解散、幹部たちを火刑に処している。 wikipedia 21世紀に発生する13日の金曜日 そこで、21世紀に13日の金曜日が発生するタイミングを求めてみました。手作業で確認してもいいのですが、どうせなので勉強中のGo言語を使って楽をしています。 作成したプログラムは以下の通りです。 21世紀に発生する13日の金曜日、CSVでの結果は以下の通りとなりました。 2000/10/13,2001/04/13,2001/07/13,2002/09/13,2002/12/13,2003/06/13,2004/02/13,2004/08/13,2005/05/13,2006/01/13,2006/10/13,2007/04/13,2007/07/13,2008/06/13,2009/02/13,2009/03/13,2009/11/13,2010/08/13,2011/05/13,2012/01/13,2012/04/13,2012/07/13,2013/09/13,2013/12/13,2014/06/13,2015/02/13,2015/03/13,2015/11/13,2016/05/13,2017/01/13,2017/10/13,2018/04/13,2018/07/13,2019/09/13,2019/12/13,2020/03/13,2020/11/13,2021/08/13,2022/05/13,2023/01/13,2023/10/13,2024/09/13,2024/12/13,2025/06/13,2026/02/13,2026/03/13,2026/11/13,2027/08/13,2028/10/13,2029/04/13,2029/07/13,2030/09/13,2030/12/13,2031/06/13,2032/02/13,2032/08/13,2033/05/13,2034/01/13,2034/10/13,2035/04/13,2035/07/13,2036/06/13,2037/02/13,2037/03/13,2037/11/13,2038/08/13,2039/05/13,2040/01/13,2040/04/13,2040/07/13,2041/09/13,2041/12/13,2042/06/13,2043/02/13,2043/03/13,2043/11/13,2044/05/13,2045/01/13,2045/10/13,2046/04/13,2046/07/13,2047/09/13,2047/12/13,2048/03/13,2048/11/13,2049/08/13,2050/05/13,2051/01/13,2051/10/13,2052/09/13,2052/12/13,2053/06/13,2054/02/13,2054/03/13,2054/11/13,2055/08/13,2056/10/13,2057/04/13,2057/07/13,2058/09/13,2058/12/13,2059/06/13,2060/02/13,2060/08/13,2061/05/13,2062/01/13,2062/10/13,2063/04/13,2063/07/13,2064/06/13,2065/02/13,2065/03/13,2065/11/13,2066/08/13,2067/05/13,2068/01/13,2068/04/13,2068/07/13,2069/09/13,2069/12/13,2070/06/13,2071/02/13,2071/03/13,2071/11/13,2072/05/13,2073/01/13,2073/10/13,2074/04/13,2074/07/13,2075/09/13,2075/12/13,2076/03/13,2076/11/13,2077/08/13,2078/05/13,2079/01/13,2079/10/13,2080/09/13,2080/12/13,2081/06/13,2082/02/13,2082/03/13,2082/11/13,2083/08/13,2084/10/13,2085/04/13,2085/07/13,2086/09/13,2086/12/13,2087/06/13,2088/02/13,2088/08/13,2089/05/13,2090/01/13,2090/10/13,2091/04/13,2091/07/13,2092/06/13,2093/02/13,2093/03/13,2093/11/13,2094/08/13,2095/05/13,2096/01/13,2096/04/13,2096/07/13,2097/09/13,2097/12/13,2098/06/13,2099/02/13,2099/03/13,2099/11/13,2100/08/13 13日の金曜日ということで、JSON形式でも出力できるようにしています。 [{"Year":2000,"Month":10,"Day":13},{"Year":2001,"Month":4,"Day":13},{"Year":2001,"Month":7,"Day":13},{"Year":2002,"Month":9,"Day":13},{"Year":2002,"Month":12,"Day":13},{"Year":2003,"Month":6,"Day":13},{"Year":2004,"Month":2,"Day":13},{"Year":2004,"Month":8,"Day":13},{"Year":2005,"Month":5,"Day":13},{"Year":2006,"Month":1,"Day":13},{"Year":2006,"Month":10,"Day":13},{"Year":2007,"Month":4,"Day":13},{"Year":2007,"Month":7,"Day":13},{"Year":2008,"Month":6,"Day":13},{"Year":2009,"Month":2,"Day":13},{"Year":2009,"Month":3,"Day":13},{"Year":2009,"Month":11,"Day":13},{"Year":2010,"Month":8,"Day":13},{"Year":2011,"Month":5,"Day":13},{"Year":2012,"Month":1,"Day":13},{"Year":2012,"Month":4,"Day":13},{"Year":2012,"Month":7,"Day":13},{"Year":2013,"Month":9,"Day":13},{"Year":2013,"Month":12,"Day":13},{"Year":2014,"Month":6,"Day":13},{"Year":2015,"Month":2,"Day":13},{"Year":2015,"Month":3,"Day":13},{"Year":2015,"Month":11,"Day":13},{"Year":2016,"Month":5,"Day":13},{"Year":2017,"Month":1,"Day":13},{"Year":2017,"Month":10,"Day":13},{"Year":2018,"Month":4,"Day":13},{"Year":2018,"Month":7,"Day":13},{"Year":2019,"Month":9,"Day":13},{"Year":2019,"Month":12,"Day":13},{"Year":2020,"Month":3,"Day":13},{"Year":2020,"Month":11,"Day":13},{"Year":2021,"Month":8,"Day":13},{"Year":2022,"Month":5,"Day":13},{"Year":2023,"Month":1,"Day":13},{"Year":2023,"Month":10,"Day":13},{"Year":2024,"Month":9,"Day":13},{"Year":2024,"Month":12,"Day":13},{"Year":2025,"Month":6,"Day":13},{"Year":2026,"Month":2,"Day":13},{"Year":2026,"Month":3,"Day":13},{"Year":2026,"Month":11,"Day":13},{"Year":2027,"Month":8,"Day":13},{"Year":2028,"Month":10,"Day":13},{"Year":2029,"Month":4,"Day":13},{"Year":2029,"Month":7,"Day":13},{"Year":2030,"Month":9,"Day":13},{"Year":2030,"Month":12,"Day":13},{"Year":2031,"Month":6,"Day":13},{"Year":2032,"Month":2,"Day":13},{"Year":2032,"Month":8,"Day":13},{"Year":2033,"Month":5,"Day":13},{"Year":2034,"Month":1,"Day":13},{"Year":2034,"Month":10,"Day":13},{"Year":2035,"Month":4,"Day":13},{"Year":2035,"Month":7,"Day":13},{"Year":2036,"Month":6,"Day":13},{"Year":2037,"Month":2,"Day":13},{"Year":2037,"Month":3,"Day":13},{"Year":2037,"Month":11,"Day":13},{"Year":2038,"Month":8,"Day":13},{"Year":2039,"Month":5,"Day":13},{"Year":2040,"Month":1,"Day":13},{"Year":2040,"Month":4,"Day":13},{"Year":2040,"Month":7,"Day":13},{"Year":2041,"Month":9,"Day":13},{"Year":2041,"Month":12,"Day":13},{"Year":2042,"Month":6,"Day":13},{"Year":2043,"Month":2,"Day":13},{"Year":2043,"Month":3,"Day":13},{"Year":2043,"Month":11,"Day":13},{"Year":2044,"Month":5,"Day":13},{"Year":2045,"Month":1,"Day":13},{"Year":2045,"Month":10,"Day":13},{"Year":2046,"Month":4,"Day":13},{"Year":2046,"Month":7,"Day":13},{"Year":2047,"Month":9,"Day":13},{"Year":2047,"Month":12,"Day":13},{"Year":2048,"Month":3,"Day":13},{"Year":2048,"Month":11,"Day":13},{"Year":2049,"Month":8,"Day":13},{"Year":2050,"Month":5,"Day":13},{"Year":2051,"Month":1,"Day":13},{"Year":2051,"Month":10,"Day":13},{"Year":2052,"Month":9,"Day":13},{"Year":2052,"Month":12,"Day":13},{"Year":2053,"Month":6,"Day":13},{"Year":2054,"Month":2,"Day":13},{"Year":2054,"Month":3,"Day":13},{"Year":2054,"Month":11,"Day":13},{"Year":2055,"Month":8,"Day":13},{"Year":2056,"Month":10,"Day":13},{"Year":2057,"Month":4,"Day":13},{"Year":2057,"Month":7,"Day":13},{"Year":2058,"Month":9,"Day":13},{"Year":2058,"Month":12,"Day":13},{"Year":2059,"Month":6,"Day":13},{"Year":2060,"Month":2,"Day":13},{"Year":2060,"Month":8,"Day":13},{"Year":2061,"Month":5,"Day":13},{"Year":2062,"Month":1,"Day":13},{"Year":2062,"Month":10,"Day":13},{"Year":2063,"Month":4,"Day":13},{"Year":2063,"Month":7,"Day":13},{"Year":2064,"Month":6,"Day":13},{"Year":2065,"Month":2,"Day":13},{"Year":2065,"Month":3,"Day":13},{"Year":2065,"Month":11,"Day":13},{"Year":2066,"Month":8,"Day":13},{"Year":2067,"Month":5,"Day":13},{"Year":2068,"Month":1,"Day":13},{"Year":2068,"Month":4,"Day":13},{"Year":2068,"Month":7,"Day":13},{"Year":2069,"Month":9,"Day":13},{"Year":2069,"Month":12,"Day":13},{"Year":2070,"Month":6,"Day":13},{"Year":2071,"Month":2,"Day":13},{"Year":2071,"Month":3,"Day":13},{"Year":2071,"Month":11,"Day":13},{"Year":2072,"Month":5,"Day":13},{"Year":2073,"Month":1,"Day":13},{"Year":2073,"Month":10,"Day":13},{"Year":2074,"Month":4,"Day":13},{"Year":2074,"Month":7,"Day":13},{"Year":2075,"Month":9,"Day":13},{"Year":2075,"Month":12,"Day":13},{"Year":2076,"Month":3,"Day":13},{"Year":2076,"Month":11,"Day":13},{"Year":2077,"Month":8,"Day":13},{"Year":2078,"Month":5,"Day":13},{"Year":2079,"Month":1,"Day":13},{"Year":2079,"Month":10,"Day":13},{"Year":2080,"Month":9,"Day":13},{"Year":2080,"Month":12,"Day":13},{"Year":2081,"Month":6,"Day":13},{"Year":2082,"Month":2,"Day":13},{"Year":2082,"Month":3,"Day":13},{"Year":2082,"Month":11,"Day":13},{"Year":2083,"Month":8,"Day":13},{"Year":2084,"Month":10,"Day":13},{"Year":2085,"Month":4,"Day":13},{"Year":2085,"Month":7,"Day":13},{"Year":2086,"Month":9,"Day":13},{"Year":2086,"Month":12,"Day":13},{"Year":2087,"Month":6,"Day":13},{"Year":2088,"Month":2,"Day":13},{"Year":2088,"Month":8,"Day":13},{"Year":2089,"Month":5,"Day":13},{"Year":2090,"Month":1,"Day":13},{"Year":2090,"Month":10,"Day":13},{"Year":2091,"Month":4,"Day":13},{"Year":2091,"Month":7,"Day":13},{"Year":2092,"Month":6,"Day":13},{"Year":2093,"Month":2,"Day":13},{"Year":2093,"Month":3,"Day":13},{"Year":2093,"Month":11,"Day":13},{"Year":2094,"Month":8,"Day":13},{"Year":2095,"Month":5,"Day":13},{"Year":2096,"Month":1,"Day":13},{"Year":2096,"Month":4,"Day":13},{"Year":2096,"Month":7,"Day":13},{"Year":2097,"Month":9,"Day":13},{"Year":2097,"Month":12,"Day":13},{"Year":2098,"Month":6,"Day":13},{"Year":2099,"Month":2,"Day":13},{"Year":2099,"Month":3,"Day":13},{"Year":2099,"Month":11,"Day":13},{"Year":2100,"Month":8,"Day":13}] おわりに 日本で仏滅を忌嫌うように、海外では13日の金曜日を嫌っている人がいる…かもしれません。 グローバルな社会を生きる我々は、様々な文化の中で親しまれている、吉日や凶日を知っておくべきではないのでしょうか。
再帰処理してみた
2016/11/30
はじめに Go言語を使っているときに、「再帰処理できるのか?」と疑問に思ったので試してみました。 どういった問題が再帰処理に向いているのか分からないので、とりあえず素数判定の処理を作成しています。 素数判定 標準入力された数値が素数か判断するプログラムです。 これを元に、標準入力された数値以下の素数をすべて出力するプログラムも作ってみました。 おわりに 今回は、再帰処理が行えることの確認がメインテーマです。100万以下のすべての素数を求めたところ、2時間20分かかりました。効率とか速度とかは度外視しているので、その辺は何卒ご容赦下さい。 学生時代、再帰処理の課題に苦労し「全部while文でいいじゃねぇか」と思っていましたが、再帰処理が使えてよかったと思える場面が来るのでしょうか。
8進数のエラーについて
2016/11/30
はじめに Go言語を使っていたら見慣れないエラーが出てたので調べてみました。 エラーの内容 試験用にサンプルの日付データを作っていたら、以下のようなコンパイルエラーとなりました。 malformed octal constant malformed integer constant: 08 エラーとなった原因のコードはこちらです。 t = time.Date(2016, time.Month(11), 08, 00, 00, 00, 00, time.Local) 原因 Go言語は先頭に0が付いた数値を8進数だと認識します。08は8進数としては存在しない値のためエラーとなってしまうのでした。同様に、09も同じエラーとなります。 対策 単純に対策をするのであれば、以下のように08から0を除いてしまえばエラーは解消されます。 t = time.Date(2016, time.Month(11), 8, 00, 00, 00, 00, time.Local) どうしても08、09と記載したい、そんなときには、数値を"で囲って文字列として指定しておき、文字列から数値に変換させれば大丈夫です。ただし、標準で用意されているstrconv.Atoi関数は2つの戻り値を返すので、そのままでは使えません。以下のように、変換用の関数を用意する必要があります。 package main import ( "fmt" "os" "strconv" "time" ) func main() { t := time.Date(2016, time.Month(atoi("11")), atoi("08"), atoi("00"), atoi("00"), atoi("00"), atoi("00"), time.Local) fmt.Println(t) } func atoi(str string) int { num, err := strconv.Atoi(str) if err !…
Go言語で構造体のスライスを扱ってみる
2016/11/30
Go言語で構造体のスライスを扱おうとしたときに少し悩んだので、まとめておきます。 ここで構造体やスライスについて詳しく説明はしません。詳細はA Tour of Goなどに記載されているので、そちらをご確認下さい。 今回は、構造体を要素として持つスライスを扱う方法をまとめています。 いろいろな操作 要素にする構造体 今回の説明で使用する構造体は以下の通り定義されています。 社員番号(number)と名前(name)を持つ社員(employee)型です。スライスで複数人の社員情報をまとめて扱うようなイメージです。 type employee struct { number int name string } スライスの作成 以下のようにmake関数を使えば、要素数が0のemployee型のスライスを作成することが出来ます。 employees := make([]employee, 0) スライスの作成と初期化をまとめて行うこともできます。 employees := []employee{employee{1, "Taro"}} 複数の要素を持つスライスを1行で書くことも可能です。 employees := []employee{employee{1, "Taro"}, employee{2, "Jiro"}, employee{3, "Saburo"}} 要素の追加 既存のスライスに対して、要素を追加させるには以下のように記載します。 employees = append(employees, employee{4, "Shiro"}) 要素の削除 組込み関数にはスライスの要素を削除する仕組みは実装されていません。そのため、個別に関数を作成する必要があります。例としては、以下のような関数で要素の削除機能が実現できます。 func delete(employees []employee, n int) []employee { result := make([]employee, 0) for i, v := range employees { if i != n { result = append(result, employee{v.…