2020年03月14日 に更新

golangのtips

コンテンツへスキップ スライス(slice)とマップ(map)の簡単な説明 スライス(slice)が他の言語でいうところの「配列」みたいなもの マップ(map)が他の言語でいうところの「連想配列」みたいなもの スライスの定義 var 変数名 []型 変数名 := []型{} package main import "fmt" type User struct { ID int Name string } func main() { // 定義その1&要素追加 var sample []User sample = append(sample, User{ ID: 1, Name: "test", }) // 定義その2 sample2 := []User{} fmt.Print(sample) fmt.Print(sample2) } マップの定義 var 変数名 map[型]型 変数名 := map[型]型{} package main import "fmt" func main() { // 定義その1&要素追加 var sample map[string]interface{} sample = map[string]interface{}{} sample["ID"] = 1 sample["Name"] = "test" // 定義その2 sample2 := map[string]interface{}{} fmt.Print(sample) fmt.Print(sample2) } スライスの追加・削除 Go言語では配列は固定長、スライスは可変長とのこと。 他の言語で使うような配列は Go言語でいうところのスライスにあたる。 要素を追加&削除する 要素を追加するには append() を使う スライスの要素を削除する機能はないので自分で作る package main import ( "fmt" ) type SliceSample struct { List []string } func (m *SliceSample) Set(value string) { m.List = append(m.List, value) } func (s *SliceSample) Remove(index int) { res := []string{} for i, v := range s.List { if i == index { continue } res = append(res, v) } s.List = res } func print(v interface{}) { fmt.Print(v) fmt.Print("\n") } func main() { ss := new(SliceSample) print(ss.List) // 追加 ss.Set("test") ss.Set("test2") ss.Set("test3") print(ss.List) // 削除 ss.Remove(0) // 存在しない要素を削除してみる ss.Remove(10) print(ss.List) } マップの追加・削除 マップは連想配列にあたる。 要素を追加&削除する 要素を追加する際に nil チェックをしないとバグの原因になったりする 要素を削除するには delete() を使う package main import ( "fmt" ) type MapSample struct { List map[string]int } func (m *MapSample) Set(key string, value int) { if m.List == nil { m.List = map[string]int{} } m.List[key] = value } func (m *MapSample) Remove(key string) { delete(m.List, key) } func print(v interface{}) { fmt.Print(v) fmt.Print("\n") } func main() { ms := new(MapSample) print(ms.List) // 追加 ms.Set("test", 123) ms.Set("test2", 456) ms.Set("test3", 789) print(ms.List) // 削除 ms.Remove("test") // 存在しない要素を削除してみる ms.Remove("test4") print(ms.List) }
逆引きGolang 文字列 日付と時刻 数値 配列 マップ 正規表現 ファイル ディレクトリ goroutine 正規表現を使う 文字にマッチさせる 繰り返し文字とマッチさせる 数字だけ・アルファベットだけとマッチさせる 改行コードを含む文字列にマッチさせる 正規表現を使って文字列を置き換える n番めのマッチを見つける パターンで区切られたレコードを読む マッチした文字列を全て抜き出して配列へ格納する 正規表現にコメントを付ける 正規表現内でString型変数を使う 正規表現を使う 正規表現はregexpパッケージを使用します。 regexp.Compile()か regexp.MustCompile()で初期化・コンパイルを行います。 MustCompile()にすると、正規表現の解析に失敗したときはpanicを起こします。 なお、後述しますが、正規表現はバッククォーテーション(``)で囲むのがよいです。 package main import "fmt" import "regexp" func main() { r := regexp.MustCompile(`golang`) fmt.Println(r) // =>"golang" } 文字にマッチさせる 文字列にマッチするかどうかを確認するには (*Regexp) MatchString() を使います。 使える正規表現はRE2 Standardとのことです。 正規表現などを記載する文字列リテラルにダブルクオーテーション(")を使う場合はエスケープを忘れずに。 特殊文字を一切解釈しない「未加工文字列リテラル」はシングルクオーテーション(')ではなく バッククォーテーション(`)を使うので注意。シングルクオーテーションはrune(UTF8文字)を表す表記です。 たとえば、数値マッチさせる場合には r = regexp.MustCompile("\\d") // OK r = regexp.MustCompile(`\d`) // OK r = regexp.MustCompile('\d') // NG のような表記を使います。基本はバッククォーテーションということでよいでしょう。 package main import "fmt" import "regexp" func main() { r := regexp.MustCompile(`abc`) fmt.Println(r.MatchString("hello")) // => false fmt.Println(r.MatchString("hello abc")) // => true } 繰り返し文字とマッチさせる *,+,?などで繰り返しも対応できます。 package main import "fmt" import "regexp" func main() { check_regexp(`a*c`, "abc") // => "true" check_regexp(`a*c`, "ac") // => "true" check_regexp(`a*c`, "aaaaaac") // => "true" check_regexp(`a*c`, "c") // => "true" check_regexp(`a*c`, "abccccc") // => "true" check_regexp(`a*c`, "abd") // => "false" check_regexp(`a+c`, "abc") // => "false" check_regexp(`a+c`, "ac") // => "true" check_regexp(`a+c`, "aaaaaac") // => "true" check_regexp(`a+c`, "c") // => "false" check_regexp(`a+c`, "abccccc") // => "false" check_regexp(`a+c`, "abd") // => "false" check_regexp(`a?c`, "abc") // => "true" check_regexp(`a?c`, "ac") // => "true" check_regexp(`a?c`, "aaaaaac") // => "true" check_regexp(`a?c`, "c") // => "true" check_regexp(`a?c`, "abccccc") // => "true" check_regexp(`a?c`, "abd") // => "false" } func check_regexp(reg, str string) { fmt.Println(regexp.MustCompile(reg).Match([]byte(str))) } 数字だけ・アルファベットだけとマッチさせる package main import "fmt" import "regexp" func main() { check_regexp(`[ABZ]`, "A") // => "true" check_regexp(`[ABZ]`, "Z") // => "true" check_regexp(`[ABZ]`, "Q") // => "false" check_regexp(`[0-9]`, "5") // => "true" check_regexp(`[0-9]`, "A") // => "false" check_regexp(`[A-Z]`, "A") // => "true" check_regexp(`[A-Z]`, "5") // => "false" check_regexp(`[A-Z]`, "a") // => "false" check_regexp(`[^0-9]`, "A") // => "true" check_regexp(`[^0-9]`, "5") // => "false" } //func check_regexp(reg, str string) { // fmt.Println(regexp.MustCompile(reg).Match([]byte(str))) //} 改行コードを含む文字列にマッチさせる 改行コードを含む複数ラインに対するマッチを行うには、 正規表現の冒頭に(?m)と書くことで対応できます。 package main import "fmt" import "regexp" func main() { txt := "hello,\nworld" check_regexp(`(?m)^(w.*)$`, txt) } //func check_regexp(reg, str string) { // fmt.Println(regexp.MustCompile(reg).Match([]byte(str))) //} 正規表現を使って文字列を置き換える ReplaceAllString()を使います。 package main import "fmt" import "regexp" func main() { str := "Copyright 2015 by ASHITANI Tatsuji." rep := regexp.MustCompile(`[A-Za-z]*right`) str = rep.ReplaceAllString(str, "Copyleft") fmt.Println(str) // => "Copyleft 2015 by ASHITANI Tatsuji." } n番めのマッチを見つける 見つけたグループを指定しつつ置換をしたい場合は$1などを使います。 package main import "fmt" import "regexp" func main() { str := "123456" rep := regexp.MustCompile(`1(.)3(.)5(.)`) str = rep.ReplaceAllString(str, "1($1)3($2)5($3)") fmt.Println(str) // => "1(2)3(4)5(6)" } パターンで区切られたレコードを読む Split(s string, n int)を使います。nは回数指定で、負を指定すれば全て行います。 package main import "fmt" import "regexp" func main() { str := "001,ASHITANI Tatsuji, Yokohama" rep := regexp.MustCompile(`\s*,\s*`) result := rep.Split(str, -1) fmt.Println(result[0]) // = >"001" fmt.Println(result[1]) // = >"ASHITANI Tatsuji" fmt.Println(result[2]) // = >"Yokohama" } マッチした文字列を全て抜き出して配列へ格納する FindAllStringSubmatch()を使います。 グルーピングを指定すると、[[マッチ全体, 1つ目のグループ、2つめのグループ、、], ...] のようなスライスが返ります。 package main import "fmt" import "regexp" func main() { s := "hoge:0045-111-2222 boke:0045-222-2222" r := regexp.MustCompile(`[\d\-]+`) fmt.Println(r.FindAllStringSubmatch(s, -1)) // => "[[0045-111-2222] [0045-222-2222]]" r2 := regexp.MustCompile(`(\S+):([\d\-]+)`) result := r2.FindAllStringSubmatch(s, -1) fmt.Println(result[0]) // => "[hoge:0045-111-2222 hoge 0045-111-2222]" fmt.Println(result[1]) // => "[boke:0045-222-2222 boke 0045-222-2222]" } 正規表現にコメントを付ける rubyには正規表現を見やすくするxオプションがありますが、golangにはなさそうなので、 自前で実装します。といっても空白とコメントを削除するだけですが。 package main import "fmt" import "regexp" func main() { r := `(\S+): # 名前 ([\d\-]+) # 電話番号 ` str := "hoge:0045-111-2222 boke:0045-222-2222" result := find_x(r, str) fmt.Println(result[0]) // => "[hoge:0045-111-2222 hoge 0045-111-2222]" fmt.Println(result[1]) // => "[boke:0045-222-2222 boke 0045-222-2222]" } func find_x(r, str string) [][]string { com := regexp.MustCompile(`(?m)(\s+)|(\#.*$)`) r = com.ReplaceAllString(r, "") reg := regexp.MustCompile(r) return reg.FindAllStringSubmatch(str, -1) } 正規表現内でString型変数を使う Rubyと違って正規表現リテラルがあるわけではないので、 stringを編集してcompile()です。 package main import "fmt" import "regexp" func main() { regEx := `^a` reg := regexp.MustCompile(regEx) fmt.Println(reg.FindAllStringSubmatch("abc", -1)) // =>[[a]] } This page is created by T.Ashitani
CLOSE 最初に読むおすすめ記事 エンジニアの情報発信 仕事/キャリア ブロックチェーン ブロックチェーン Bitcoin Ethereum CLOSE キーワードで記事を検索 CLOSE 当ブログのおすすめ記事10選はこちら! HOMEGoGolangでメソッドのオーバーライドをする方法 structのメソッドを別のstructで使い回す Golangにはクラスはありませんがstructを使って似た機能を定義することができます。 このstructを別のstructに埋め込むことで別のstructからも同じメソッドを使用することができます。 Go type Parent struct { name string } func (p *Parent) printName() { log.Println(p.name) } type Child struct { Parent } func main() { p := &Parent{ name: "parent" } c := &Child{ *p } c.printName() // "Parent" } 12345678910111213141516171819 type Parent struct { name string} func (p *Parent) printName() { log.Println(p.name)} type Child struct { Parent} func main() { p := &Parent{ name: "parent" } c := &Child{ *p } c.printName() // "Parent"} Parent structを使ってChild structを生成します。 生成したChildからParentのprintNameメソッドを呼び出すことができます。 structのメソッドをオーバーライドする 埋め込んだstructのメソッドをそのまま使うこともできるし、同名のメソッドを定義することでオーバーライドすることができます。 クラスではないですが、Golangでも同様の使い方ができるのでぜひ試してみてください。 Go type Parent struct { name string } func (p *Parent) printName() { log.Println(p.name) } type Child struct { Parent } func (p *Child) printName() { log.Println("Child") } func main() { p := &Parent{ name: "parent" } c := &Child{ *p } c.printName() // "Child" } 1234567891011121314151617181920212223 type Parent struct { name string} func (p *Parent) printName() { log.Println(p.name)} type Child struct { Parent} func (p *Child) printName() { log.Println("Child")} func main() { p := &Parent{ name: "parent" } c := &Child{ *p } c.printName() // "Child"}   The following two tabs change content below.この記事を書いた人最新の記事 髙妻智一 2013年CyberAgent新卒入社 スマホゲームを作る子会社に所属し、サーバーサイドのエンジニアを担当。2年目の終わりから新規子会社の立ち上げに参加し、サーバーサイドのエンジニアリーダーとしてサービースのリリースから運用までを担当。 2018年仮想通貨のスマホウォレットを提供するGinco Incにブロックチェーンエンジニアとして入社。 最新記事 by 髙妻智一 (全て見る) 【無料公開】「Goで始めるBitcoin」3章 Bitcoinノードとの通信 技術書典8 - 2020-03-08 エンジニアがゼロから技術ブログを書くための方法をまとめました - 2019-05-25 FlutterからCloud Firestoreのデータを追加、更新、取得、削除する方法 - 2019-05-23 よく読まれている関連記事はこちら ツイート シェア はてブ LINE Pocket feedly コメントを残す コメントをキャンセル GCPのContainer RegistryにDocker Imageをアップする方法 Kubernetes IngressのヘルスチェックにReadiness Probeを使う RECOMMENDこちらの記事も人気です。 Go 2018.7.21 GolangのLogger「zap」をStackdriverに対応させる方法 Go 2018.7.14 GolangのGoConveyでテストのSetUpとTearDownを行… Go 2018.7.13 Cloud PubSubなどのgRPCを使ったサービスでrpc erro… Go 2018.6.12 Golangのchannelへのデータの送受信について Go 2018.5.26 MacでGoの環境を構築してghqとpecoで快適環境を作る Go 2018.6.13 Golangで並列処理をまとめるsync.waitGroupとerror… Go 2019.1.7 gomobileのインストールからAndroid NDKの設定まで Go 2018.6.8 Golangでスタックトレースを出力できるpkg/errorsについて プロフィール Follow @Tomokazu106 髙妻智一(コウヅマ トモカズ) エンジニアのキャリア、技術トレンド、アウトプット方法について発信中|月間3万PVの技術ブログ運営中|エンジニア兼PMが得意|ブロックチェーンとバックエンドが主| 詳細はこちら イベント登壇・メディア掲載履歴はこちら プライバシー・ポリシーはこちら ピックアップ記事 アーカイブ アーカイブ 月を選択 2020年3月  (1) 2019年5月  (25) 2019年4月  (29) 2019年3月  (30) 2019年2月  (2) 2019年1月  (5) 2018年12月  (10) 2018年11月  (8) 2018年10月  (9) 2018年9月  (18) 2018年8月  (12) 2018年7月  (22) 2018年6月  (11) 2018年5月  (9) 2018年4月  (11) 2018年3月  (20) 2018年2月  (20) 2018年1月  (21) 2017年12月  (20) 2017年11月  (28) 2017年10月  (18) 2017年9月  (12) 2017年8月  (12) 2017年7月  (8) 2017年6月  (6) 2017年5月  (20) カテゴリー
January 29, 2020 20:46 ns60fq Last Updated: January 29, 2020 · 26.44K · septiaji Simply output go html template execution to strings string html go Instead of executing html template into io.Writer interface like *http.ResponseWriter, sometimes we just only want strings as output from go lang html template execution. To achieve this we can simply use any types that implement io.Writer interface. For this strings case, we can use a buffer's pointer to store html template execution result then parse them to string. t := template.New("action") var err error t, err = t.ParseFiles("path/to/action.html") if err != nil { return err } key := "some strings" data := struct{ Key string }{ Key: key } var tpl bytes.Buffer if err := t.Execute(&tpl, data); err != nil { return err } result := tpl.String() happy holiday! Written by Aji Say Thanks Respond Sponsored by #native_company# #native_desc# #native_cta# Filed Under Accelerate Your Web Development Skills Awesome Job See All Jobs Post a job for only $299 Sponsored by #native_company# — Learn More #native_title# #native_desc# #native_cta#
トップ > Goのsliceで重複を削除する 重複削除処理を実装する ruby でいうところの uniq メソッドみたいなものが golang の slice にもないのかと思って調べてみたけどないらしいので、重複のある slice に対して独自に処理を実装しなければ行けない。 go は非常にシンプルでLL言語をずっと書いていたエンジニアとしては覚えることが比較的少なく、静的型付けされていて安全で、高速という点で有用なツールだと思うけど、シンプルすぎる反面、LL言語ならデフォルトのAPIやメソッドとして提供されていそうな処理が実装されてなかったりすることが多い。。。 LL言語の処理をブラックボックス化してしまうことに比べれば、いいことのように感じる一方で、これくらい用意しておいてよ~的な感想もしばしば(笑) というわけで go における slice の重複削除の実装方法を調べてみた。 方法 mapを使う mapと空のstructを使う map を使う方法 make(map[string]int) or make(map[string]bool) のようにkeyに配列の要素をおいて値を適当にintやboolをぶち込みます。 arr := [string]{"a", "b", "c", "a"} m := make(map[string]bool) uniq := [] string{} for _, ele := range arr { if !m[ele] { m[ele] = true uniq = append(uniq, ele) } } fmt.Printf("%v", uniq) // ["a", "b", "c"] どういうことかというと、重複キーがあるので、同様のキーを持つmapの場合は新しく値を上書きしない。 ここの処理で言うところの m["a"] = true は一度目はこれが呼ばれるけど、二度目はすでに true なので if句の中に入ってず、resultに a が二度入ることがない。 こんな感じでmapにboolをいれることで重複を削除する方法はgoでは一般的です。 空のstructとの合わせ技 だいたいのユースケースにおいてintかboolをぶち込む方法で事足りる前提で付け足しですが、空のstructを使っても同じことができます。 実際に出会う機会があるかはわかりませんが、メモリ的にきついめの状況があるかもしれず、intやboolでいちいちメモリ空間とってられん、的な状況があるかもしれません。(ないかもしれません) arr := [string]{"a", "b", "c", "a"} m := make(map[string]struct{}) // 空のstructを使う for _, ele := range arr { m[ele] = struct{}{} // m["a"] = struct{}{} が二度目は同じものとみなされて重複が消える。 } uniq := [] string{} for i := range m { uniq := append(uniq, i) } fmt.Printf("%v", uniq) // ["a", "b", "c"] loopを二度使わなければなりませんが、intやboolようにメモリを確保しなくていいので省メモリで実装できます。 struct{}{} はgoで出て来るお作法みないなもので、valueに意味はないよっていうこと表します。 « GoのtimeのFormat表記方法でハマったこと Goでシェルを実行するCLIToolを書く » Profile id:ema_hiro 渋谷で働いています。 Go, TypeScript, GCPが好きです。 読者です 読者をやめる 読者になる 読者になる @ema_hiroをフォロー 最新記事 TSLint -> ESLint に乗り換える iTerm2 が Dock にアプリが表示されなくなる問題 DeNA を退職しました 障害対応時のTODOリストをまとめてみる ドメイン名からIPアドレスを調べる 注目記事 月別アーカイブ スターをつけました 引用をストックしました ストック一覧を見る 閉じる 引用するにはまずログインしてください ログイン 閉じる 引用をストックできませんでした。再度お試しください 閉じる 限定公開記事のため引用できません。 読者です 読者をやめる 読者になる 読者になる
QiitaYou are not logged in to any teamLog in to Qiita Team...CommunityList of all usersList of all organizatioinsAdvent CalendarQiita JobsQiitadon (β)Qiita ZineCommunity GuidelineHow to write good articlesSignupLogin @kanuma1984posted at 2016-02-11Improve articleSend edit requestArticle informationRevisionsEdit RequestsShow all likersShow article in MarkdownReport articleGoでディレクトリ&ファイル名を指定してビルドGoMore than 3 years have passed since last update. 背景 go buildしたらワーキングディレクトリ直下に実行ファイルが生成された ⇒ここじゃやだ、毎回移動するのめんどい ってのが背景です。 調べた・・・ 「-o」ってオプションでできそうです。 やってみる コチラのプロジェクトを使ってやってみます。 # 出力先はsrcと同階層のbinディレクトリの下 $ go build -o ../../bin/v1 # treeで見てみる $ cd /tmp/vendor-test $ tree . ├── bin │   └── v1 └── src └── v1 ├── glide.lock ├── glide.yaml ├── main.go できてる! いいね! だが待て・・・動かなければ意味がない # 移動 $ cd /tmp/vendor-test/bin # 実行 $ ./v1 2016/02/11 14:31:30.470609 Starting Goji on [::]:8000 起動できてる! Edit requestStock7section9@kanuma1984FollowWhy not register and get more from Qiita?We will deliver articles that match youBy following users and tags, you can catch up information on technical fields that you are interested in as a wholeyou can read useful information later efficientlyBy "stocking" the articles you like, you can search right awayWhat you can do with signing upSign upLoginCommentsNo commentsSign up for free and join this conversation.Sign UpIf you already have a Qiita account Login Why do not you register as a user and use Qiita more conveniently?You need to log in to use this function. Qiita can be used more conveniently after logging in.You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.We will deliver articles that match youBy following users and tags, you can catch up information on technical fields that you are interested in as a wholeyou can read useful information later efficientlyBy "stocking" the articles you like, you can search right awaySign upLogin ユーザーは見つかりませんでした
QiitaYou are not logged in to any teamLog in to Qiita Team...CommunityList of all usersList of all organizatioinsAdvent CalendarQiita JobsQiitadon (β)Qiita ZineCommunity GuidelineHow to write good articlesSignupLogin @trewanekposted at 2019-04-17Improve articleSend edit requestArticle informationRevisionsEdit RequestsShow all likersShow article in MarkdownReport articleGO1.11.9のコンテナでgo testしようとするとexec: "gcc": executable file not found in $PATH と怒られるGoGoの公式DockerImageでgo testしたいのに exec: "gcc": executable file not found in $PATH と怒られる問題。 ググって下記にたどり着く https://github.com/golang/go/issues/27303 goenv で環境変数を確かめてみると CGO_ENABLED="1" になっていた。 export CGO_ENABLED=0 でこいつを無効にしてやると go test が通るようになった。 Edit requestStock4@trewanekPHPが親鳥です。最近はGolang。FollowWhy not register and get more from Qiita?We will deliver articles that match youBy following users and tags, you can catch up information on technical fields that you are interested in as a wholeyou can read useful information later efficientlyBy "stocking" the articles you like, you can search right awayWhat you can do with signing upSign upLoginCommentsNo commentsSign up for free and join this conversation.Sign UpIf you already have a Qiita account Login Why do not you register as a user and use Qiita more conveniently?You need to log in to use this function. Qiita can be used more conveniently after logging in.You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.We will deliver articles that match youBy following users and tags, you can catch up information on technical fields that you are interested in as a wholeyou can read useful information later efficientlyBy "stocking" the articles you like, you can search right awaySign upLogin ユーザーは見つかりませんでした