├── doc ├── markdown │ └── .gitkeep ├── html │ ├── gopher.png │ ├── favicon.ico │ ├── LICENSE.highlightjs.txt │ ├── styles │ │ └── github.css │ ├── github.css │ └── highlight.pack.js ├── template │ ├── after_body.html │ ├── before_body.html │ └── header.html └── make_doc.rb ├── pkg ├── tips_file │ ├── test.txt │ ├── foo.csv │ ├── fmtTxt.txt │ └── tips_file.go ├── tips_num │ └── tips_num.go ├── tips_dir │ └── tips_dir.go ├── tips_regexp │ └── tips_regexp.go ├── tips_goroutine │ └── tips_goroutine.go ├── tips_map │ └── tips_map.go ├── tips_time │ └── tips_time.go ├── tips_string │ └── tips_string.go └── tips_slice │ └── tips_slice.go ├── .gitignore ├── main.go ├── LICENSE └── README.md /doc/markdown/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pkg/tips_file/test.txt: -------------------------------------------------------------------------------- 1 | HELLO, GOLANG! -------------------------------------------------------------------------------- /pkg/tips_file/foo.csv: -------------------------------------------------------------------------------- 1 | this,is 2 | a,test 3 | -------------------------------------------------------------------------------- /doc/html/gopher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashitani/golangtips/HEAD/doc/html/gopher.png -------------------------------------------------------------------------------- /doc/html/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashitani/golangtips/HEAD/doc/html/favicon.ico -------------------------------------------------------------------------------- /pkg/tips_file/fmtTxt.txt: -------------------------------------------------------------------------------- 1 | 100001鈴木一郎太12342001 2 | 100002田中三郎太12351980 3 | 100003佐藤花子姫12361990 4 | -------------------------------------------------------------------------------- /doc/template/after_body.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /golangtips 2 | /pkg/tips_map/tips_map 3 | /pkg/tips_file/tips_file 4 | /pkg/tips_file/stat.rb 5 | /pkg/tips_file/test.bak 6 | /pkg/tips_goroutine/count.txt 7 | /EUC.txt 8 | /doc/template/adsense.html 9 | /doc/publish.rb 10 | /doc/html/*.html 11 | /doc/markdown/*.md 12 | /test/ 13 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | 逆引きGolang 3 | 4 | [逆引きRuby](http://www.namaraii.com/rubytips)の内容をGolang化したものです。 5 | [こちら](http://ashitani.jp/golangtips)で公開しています。 6 | 7 | */ 8 | 9 | package main 10 | 11 | import ( 12 | . "./pkg/tips_map" 13 | . "./pkg/tips_num" 14 | . "./pkg/tips_regexp" 15 | . "./pkg/tips_slice" 16 | . "./pkg/tips_string" 17 | . "./pkg/tips_time" 18 | ) 19 | 20 | func main() { 21 | Tips_string() 22 | Tips_num() 23 | Tips_time() 24 | Tips_slice() 25 | Tips_map() 26 | Tips_regexp() 27 | } 28 | -------------------------------------------------------------------------------- /doc/template/before_body.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

逆引きGolang

4 | 5 | 20 | 21 |
22 |
23 | 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Tatsuji Ashitani 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /doc/template/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /doc/html/LICENSE.highlightjs.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006, Ivan Sagalaev 2 | All rights reserved. 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of highlight.js nor the names of its contributors 12 | may be used to endorse or promote products derived from this software 13 | without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [逆引きGolang](http://ashitani.jp/golangtips) 2 | 3 | [逆引きRuby](http://www.namaraii.com/rubytips)の内容をGolang化した(しつつある)ものです。 4 | htmlは[こちら](http://ashitani.jp/golangtips)で公開しています。 5 | 6 | 誤りがあったりもっとうまく書ける場合はPull Requestを投げてください。 7 | 8 | ## 実行 9 | 10 | (内容的に全部を実行して嬉しい人はあまり居ないと思いますが..) 11 | 12 | ```golang 13 | go run main.go 14 | ``` 15 | 16 | 所々、必要なパッケージは go get してください。 17 | 18 | ## フォルダ・ファイル構成 19 | 20 | pkg/tips_HOGE/tips_HOGE.gp 以下の関数Tips_HOGE()で、HOGEに関するTipsのコードが 21 | 全て実行されます。関数はすべてHOGE_hoge()という命名規則です。 22 | 23 | ## ドキュメント生成 24 | 25 | [Pandoc](http://pandoc.org)が必要です。 26 | 27 | ``` 28 | cd doc 29 | ruby make_doc.rb 30 | ``` 31 | 32 | markdownフォルダ以下に \*.mdが、 33 | htmlフォルダ以下に \*.html が生成されます。 34 | 35 | 関数の頭の表記を下記規則に従って変換します。 36 | 37 | 38 | ```golang 39 | //--------------------------------------------------- 40 | // Tipsの名前 41 | //--------------------------------------------------- 42 | /* 43 | コメント(markdown表記できます) 44 | */ 45 | // import "hogehoge" 46 | func HOGE_hogehoge() { 47 | 48 | } 49 | 50 | func hogehoge(){ //HOGE_hogehoge()から呼ばれる関数 51 | 52 | } 53 | ``` 54 | 55 | 基本的には各Tipsが全コピペで動作するように、 56 | 57 | ```golang 58 | package main 59 | 60 | import "fmt" 61 | ``` 62 | などを追加します。fmt以外のimport文の抽出は自動では難しいので 63 | コメントアウトして書いてあるもの(上記例では // import "hogehoge")を使います。 64 | 65 | ## License 66 | 67 | [MIT license](LICENSE) 68 | 69 | ## Credits 70 | 71 | - [RubyTips](http://www.namaraii.com/rubytips) is founded by [TAKEUCHI Hitoshi](http://www.namaraii.com/). 72 | 73 | - HTMLs are generated by [Pandoc](http://pandoc.org/) and decorated by [github.css](https://gist.github.com/andyferra/2554919). 74 | - Golang codes are highlighted by [highlight.js](https://highlightjs.org/), 75 | which is released under the [BSD License](./LICENSE.highlightjs.txt). 76 | 77 | - The Go gopher was designed by [Renee French](http://reneefrench.blogspot.com/). 78 | The gopher vector data was made by [Takuya Ueda](http://u.hinoichi.net). 79 | Licensed under the Creative Commons 3.0 Attributions license. 80 | 81 | - The Gppher favicon was designed by [mccoyst](https://github.com/mccoyst/Gophers) 82 | -------------------------------------------------------------------------------- /doc/html/styles/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | -webkit-text-size-adjust: none; 14 | } 15 | 16 | .hljs-comment, 17 | .diff .hljs-header, 18 | .hljs-javadoc { 19 | color: #998; 20 | font-style: italic; 21 | } 22 | 23 | .hljs-keyword, 24 | .css .rule .hljs-keyword, 25 | .hljs-winutils, 26 | .nginx .hljs-title, 27 | .hljs-subst, 28 | .hljs-request, 29 | .hljs-status { 30 | color: #333; 31 | font-weight: bold; 32 | } 33 | 34 | .hljs-number, 35 | .hljs-hexcolor, 36 | .ruby .hljs-constant { 37 | color: #008080; 38 | } 39 | 40 | .hljs-string, 41 | .hljs-tag .hljs-value, 42 | .hljs-phpdoc, 43 | .hljs-dartdoc, 44 | .tex .hljs-formula { 45 | color: #d14; 46 | } 47 | 48 | .hljs-title, 49 | .hljs-id, 50 | .scss .hljs-preprocessor { 51 | color: #900; 52 | font-weight: bold; 53 | } 54 | 55 | .hljs-list .hljs-keyword, 56 | .hljs-subst { 57 | font-weight: normal; 58 | } 59 | 60 | .hljs-class .hljs-title, 61 | .hljs-type, 62 | .vhdl .hljs-literal, 63 | .tex .hljs-command { 64 | color: #458; 65 | font-weight: bold; 66 | } 67 | 68 | .hljs-tag, 69 | .hljs-tag .hljs-title, 70 | .hljs-rule .hljs-property, 71 | .django .hljs-tag .hljs-keyword { 72 | color: #000080; 73 | font-weight: normal; 74 | } 75 | 76 | .hljs-attribute, 77 | .hljs-variable, 78 | .lisp .hljs-body, 79 | .hljs-name { 80 | color: #008080; 81 | } 82 | 83 | .hljs-regexp { 84 | color: #009926; 85 | } 86 | 87 | .hljs-symbol, 88 | .ruby .hljs-symbol .hljs-string, 89 | .lisp .hljs-keyword, 90 | .clojure .hljs-keyword, 91 | .scheme .hljs-keyword, 92 | .tex .hljs-special, 93 | .hljs-prompt { 94 | color: #990073; 95 | } 96 | 97 | .hljs-built_in { 98 | color: #0086b3; 99 | } 100 | 101 | .hljs-preprocessor, 102 | .hljs-pragma, 103 | .hljs-pi, 104 | .hljs-doctype, 105 | .hljs-shebang, 106 | .hljs-cdata { 107 | color: #999; 108 | font-weight: bold; 109 | } 110 | 111 | .hljs-deletion { 112 | background: #fdd; 113 | } 114 | 115 | .hljs-addition { 116 | background: #dfd; 117 | } 118 | 119 | .diff .hljs-change { 120 | background: #0086b3; 121 | } 122 | 123 | .hljs-chunk { 124 | color: #aaa; 125 | } 126 | -------------------------------------------------------------------------------- /pkg/tips_num/tips_num.go: -------------------------------------------------------------------------------- 1 | /* 2 | 数値 3 | */ 4 | 5 | package tips_num 6 | 7 | import ( 8 | "fmt" 9 | "math" 10 | "math/rand" 11 | "strconv" 12 | "time" 13 | ) 14 | 15 | //--------------------------------------------------- 16 | // 2進数・8進数・16進数で数値を扱うには 17 | //--------------------------------------------------- 18 | /* Goには2進数リテラルはありません。8(0始まり)と16(0x始まり)はあり。*/ 19 | // import "strconv" 20 | 21 | func num_Base() { 22 | i2, _ := strconv.ParseInt("10000", 2, 0) 23 | fmt.Println(i2) // =>"16" 24 | fmt.Printf("%d\n", 020) // =>"16" 25 | fmt.Printf("%d\n", 0x10) // =>"16" 26 | } 27 | 28 | //--------------------------------------------------- 29 | // 数値を2進数・8進数・16進数表現の文字列に変換するには 30 | //--------------------------------------------------- 31 | func num_Format() { 32 | s := "" 33 | s = fmt.Sprintf("%b", 255) 34 | fmt.Println(s) // => "11111111" 35 | s = fmt.Sprintf("%o", 255) 36 | fmt.Println(s) // => "11111111" 37 | s = fmt.Sprintf("%x", 255) 38 | fmt.Println(s) // => "ff" 39 | } 40 | 41 | //--------------------------------------------------- 42 | //任意のビット位置の値を参照する 43 | //--------------------------------------------------- 44 | func num_RefBit() { 45 | i := 0x10 46 | fmt.Println(refbit(i, 0)) // => "0" 47 | fmt.Println(refbit(i, 4)) // => "1" 48 | } 49 | 50 | //任意のビット位置の値を参照する 51 | func refbit(i int, b uint) int { 52 | return (i >> b) & 1 53 | } 54 | 55 | //--------------------------------------------------- 56 | // 除算の商と余りを求める 57 | //--------------------------------------------------- 58 | func num_Mod() { 59 | i := 10 60 | d := i / 3 61 | m := i % 3 62 | fmt.Println(d, m) // => 3,1 63 | } 64 | 65 | //--------------------------------------------------- 66 | // 絶対値を求める 67 | //--------------------------------------------------- 68 | func num_Abs() { 69 | // import "math" 70 | i := -5 71 | fmt.Println(math.Abs(float64(i))) // => "5" 72 | 73 | i = 100 74 | fmt.Println(math.Abs(float64(i))) // =>"100" 75 | } 76 | 77 | //--------------------------------------------------- 78 | // 小数を切り上げ・切り捨て・四捨五入するには 79 | //--------------------------------------------------- 80 | // import "math" 81 | 82 | func num_CeilFloor() { 83 | f := 3.4 84 | fmt.Println(math.Ceil(f)) // =>"4" 85 | fmt.Println(math.Trunc(f)) // =>"3" 86 | fmt.Println(round(f)) // =>"3" Roundはないらしい 87 | f = 3.5 88 | fmt.Println(round(f)) // =>"4" 89 | } 90 | 91 | // 丸め 92 | func round(f float64) float64 { 93 | return math.Floor(f + .5) 94 | } 95 | 96 | //--------------------------------------------------- 97 | // 三角関数を計算する 98 | //--------------------------------------------------- 99 | func num_SinCos() { 100 | fmt.Println(math.Sin(math.Pi / 2)) // => "1" 101 | fmt.Println(math.Cos(0)) // => "1" 102 | fmt.Println(math.Tan(0)) // => "0" 103 | } 104 | 105 | //--------------------------------------------------- 106 | // 対数を計算する 107 | //--------------------------------------------------- 108 | func num_Log() { 109 | fmt.Println(math.Log(math.E)) // => "1" 110 | fmt.Println(math.Log10(10)) // => "1" 111 | } 112 | 113 | //--------------------------------------------------- 114 | // 平方根を求める 115 | //--------------------------------------------------- 116 | func num_Sqrt() { 117 | fmt.Println(math.Sqrt(100)) // => "10" 118 | fmt.Println(math.Sqrt(10)) // => "3.1622776601683795" 119 | } 120 | 121 | //--------------------------------------------------- 122 | // 擬似乱数を生成する 123 | //--------------------------------------------------- 124 | /* 125 | Seedの与え方は[こちら](http://qiita.com/cubicdaiya/items/819886c57e9d17e4b019)。 126 | 127 | Intn(100)は[0,100)の乱数を返します。 128 | */ 129 | // import "time" 130 | // import "math/rand" 131 | 132 | func num_Rand() { 133 | 134 | rand.Seed(time.Now().UnixNano()) //Seed 135 | 136 | fmt.Println(rand.Float32()) 137 | fmt.Println(rand.Intn(100)) 138 | } 139 | 140 | //--------------------------------------------------- 141 | // 整数と浮動小数を相互変換する(精度の変換) 142 | //--------------------------------------------------- 143 | func num_Conv() { 144 | i := 1 145 | f := float64(i) 146 | fmt.Printf("%d, %f\n", i, f) 147 | 148 | f = 3.0 149 | i = int(f) 150 | fmt.Printf("%d, %f\n", i, f) 151 | } 152 | 153 | //--------------------------------------------------- 154 | // 数値 155 | //--------------------------------------------------- 156 | func Tips_num() { 157 | num_Base() // 2進数・8進数・16進数で数値を扱うには 158 | num_Format() // 数値を2進数・8進数・16進数表現の文字列に変換するには 159 | num_RefBit() // 任意のビット位置の値を参照する 160 | num_Mod() // 除算の商と余りを求める 161 | num_Abs() // 絶対値を求める 162 | num_CeilFloor() // 小数を切り上げ・切り捨て・四捨五入するには 163 | num_SinCos() // 三角関数を計算する 164 | num_Log() // 対数を計算する 165 | num_Sqrt() // 平方根を求める 166 | num_Rand() // 擬似乱数を生成する 167 | num_Conv() // 整数と浮動小数を相互変換する(精度の変換) 168 | 169 | } 170 | -------------------------------------------------------------------------------- /doc/make_doc.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # coding: utf-8 3 | 4 | # *.go -> (make_doc.rb) -> *.md -> (pandoc) -> *.html 5 | 6 | # Golang Tipsなのにrubyで生成するのかよ!というツッコミはなしで。。 7 | 8 | ## --------------------------------------------- 9 | 10 | documents=[ 11 | ["tips_string","文字列"], 12 | ["tips_time","日付と時刻"], 13 | ["tips_num","数値"], 14 | ["tips_slice","配列"], 15 | ["tips_map","マップ"], 16 | ["tips_regexp","正規表現"], 17 | ["tips_file","ファイル"], 18 | ["tips_dir","ディレクトリ"], 19 | ["tips_goroutine","goroutine"] 20 | ] 21 | 22 | markdown_folder = "markdown" 23 | html_folder = "html" 24 | template_folder ="template" 25 | go_folder="../pkg" 26 | 27 | ## トップページ作成------------------------------- 28 | 29 | fw=open(markdown_folder+"/"+"index.md","w") 30 | 31 | fw.puts <=3 && lastmode==2 111 | mode=1 112 | texts.push([title,code,func]) 113 | title="" 114 | code="" 115 | func="" 116 | end 117 | 118 | if mode==1 && lastmode==1 119 | title=l.sub(/^\/\//,"") 120 | end 121 | 122 | if mode==2 && lastmode==2 123 | code+=(l+"\n") 124 | if l=~/func (#{suf}_.*)\(/ 125 | func=$1 126 | end 127 | end 128 | lastmode=mode 129 | end 130 | 131 | ## 書き出し---------------------------- 132 | 133 | fw=open(markdown_folder+"/"+md,"w") 134 | 135 | 136 | ## 目次 137 | fw.puts "% 逆引きGolang ("+name+")" 138 | fw.puts 139 | texts.each do |x| 140 | n=x[0].strip() 141 | fw.puts "- [#{n}](##{x[2]})" 142 | end 143 | fw.puts 144 | 145 | ## 各Tips 146 | 147 | texts.each do |x| 148 | code=x[1] 149 | 150 | # コメント抽出 151 | comment=code.scan(/\/\*.*\*\//m)[0] 152 | if comment!=nil 153 | comment.sub!(/\/\*/,"") 154 | comment.sub!(/\*\//,"") 155 | end 156 | 157 | # コメント削除 158 | code.sub!(/\/\*.*\*\/( )*\n/m,"") 159 | 160 | # コードがない場合はスキップ 161 | if code.gsub(/\n/,"")=="" 162 | skip=true 163 | else 164 | skip=false 165 | end 166 | 167 | if skip==false 168 | # 冒頭にimport "fmt" 169 | code="package main\n\nimport \"fmt\"\n"+code 170 | 171 | #最初の関数名をmainに置き換える 172 | code.sub!(/func( )*#{x[2]}\(/,"func main(") 173 | 174 | # import "fmt"の次に改行がない場合は改行追加 175 | code.sub!(/import "fmt"\nfunc main/,"import \"fmt\"\n\nfunc main") 176 | 177 | # import文のコメントアウト 178 | code.gsub!(/\/\/( )*import/,"import") 179 | 180 | end 181 | 182 | # 書き出し 183 | fw.puts "## #{x[0].strip()}" 184 | fw.puts comment 185 | if skip==false 186 | fw.puts "```golang" 187 | fw.puts code 188 | fw.puts "```" 189 | end 190 | fw.puts 191 | end 192 | 193 | fw.close() 194 | 195 | end 196 | 197 | ##------ html生成 198 | 199 | com= "pandoc -s -t html5 -c github.css" 200 | com+=" -H #{template_folder}/header.html" 201 | com+=" -B #{template_folder}/before_body.html" 202 | if File.exist?("#{template_folder}/adsense.html") 203 | com+=" -B #{template_folder}/adsense.html" 204 | end 205 | com+=" -A #{template_folder}/after_body.html" 206 | 207 | 208 | Dir.glob(markdown_folder+"/*.md").each do |x| 209 | infile="#{x}" 210 | outfile = x.sub(/\.md/,".html") 211 | outfile = outfile.sub(/#{markdown_folder}/,html_folder) 212 | system (com+" -o #{outfile} #{infile}") 213 | end 214 | -------------------------------------------------------------------------------- /pkg/tips_dir/tips_dir.go: -------------------------------------------------------------------------------- 1 | /* 2 | ディレクトリ 3 | */ 4 | 5 | //package main 6 | package tips_dir 7 | 8 | import ( 9 | "fmt" 10 | "io/ioutil" 11 | "os" 12 | "path/filepath" 13 | "syscall" 14 | ) 15 | 16 | //--------------------------------------------------- 17 | // ディレクトリの作成 18 | //--------------------------------------------------- 19 | /* 20 | os.Mkdir()が使えます。第二引数はモードです。 21 | */ 22 | // import "os" 23 | 24 | func dir_MakeDir() { 25 | err := os.Mkdir("tmp", 0777) 26 | fmt.Println(err) 27 | } 28 | 29 | //--------------------------------------------------- 30 | // ディレクトリの削除 31 | //--------------------------------------------------- 32 | /* 33 | ファイルでもディレクトリでも 34 | os.Remove()が使えます。ただしディレクトリの場合、中身が空でない場合はエラーになります。 35 | */ 36 | // import "os" 37 | 38 | func dir_RemoveDir() { 39 | err := os.Remove("./tmp") 40 | fmt.Println(err) 41 | } 42 | 43 | //--------------------------------------------------- 44 | // 中身が空でないディレクトリを削除する 45 | //--------------------------------------------------- 46 | /* 47 | os.RemoveAll()が使えます。 48 | */ 49 | // import "os" 50 | 51 | func dir_RemoveDirAll() { 52 | err := os.RemoveAll("./tmp") 53 | fmt.Println(err) 54 | } 55 | 56 | //--------------------------------------------------- 57 | // ディレクトリ名を変更する 58 | //--------------------------------------------------- 59 | /* 60 | ファイルでもディレクトリでもos.Rename()が使えます。 61 | */ 62 | // import "os" 63 | 64 | func dir_Rename() { 65 | err := os.Rename("sample", "doc") 66 | fmt.Println(err) 67 | } 68 | 69 | //--------------------------------------------------- 70 | // ディレクトリの詳細情報を取得する 71 | //--------------------------------------------------- 72 | /* 73 | ファイルでもディレクトリでも同じです。 74 | [ファイルの詳細情報を取得する](http://ashitani.jp/golangtips/tips_file.html#file_Stat) 75 | を参照のこと。 76 | */ 77 | 78 | //--------------------------------------------------- 79 | // ディレクトリのファイルモードを変更する 80 | //--------------------------------------------------- 81 | /* 82 | ファイルでもディレクトリでも同じです。 83 | [ファイルモードを変更する](http://ashitani.jp/golangtips/tips_file.html#file_ChMod) 84 | を参照のこと。 85 | */ 86 | 87 | //--------------------------------------------------- 88 | // ディレクトリの所有者とグループを変更する 89 | //--------------------------------------------------- 90 | /* 91 | ファイルでもディレクトリでも同じです。 92 | [ファイルの所有者とグループを変更する](http://ashitani.jp/golangtips/tips_file.html#file_ChOwn) 93 | を参照のこと。 94 | */ 95 | 96 | //--------------------------------------------------- 97 | // ディレクトリの最終アクセス時刻と最終更新日時を変更する 98 | //--------------------------------------------------- 99 | /* 100 | ファイルでもディレクトリでも同じです。 101 | [ファイルの最終アクセス時刻と最終更新日時を変更する](http://ashitani.jp/golangtips/tips_file.html#file_ChangeTime) 102 | を参照のこと。 103 | */ 104 | 105 | //--------------------------------------------------- 106 | // カレントディレクトリの取得と変更 107 | //--------------------------------------------------- 108 | /* 109 | os.Getwd()とos.Chdir()が使えます。 110 | */ 111 | // import "os" 112 | 113 | func dir_Pwd() { 114 | // 取得 115 | p, _ := os.Getwd() 116 | fmt.Println(p) 117 | 118 | // 変更 119 | os.Chdir("/etc") 120 | 121 | // 確認 122 | p, _ = os.Getwd() 123 | fmt.Println(p) 124 | } 125 | 126 | //--------------------------------------------------- 127 | // ディレクトリ中のファイル一覧を取得する 128 | //--------------------------------------------------- 129 | /* 130 | io/ioutilのReadDir()が使えます。 131 | */ 132 | // import "io/ioutil" 133 | 134 | func dir_GetFileList() { 135 | files, _ := ioutil.ReadDir("./") 136 | for _, f := range files { 137 | fmt.Println(f.Name()) 138 | } 139 | } 140 | 141 | //--------------------------------------------------- 142 | // ワイルドカードにマッチしたファイル全てに処理を行う 143 | //--------------------------------------------------- 144 | /* 145 | path/filepathにGlob()があります。下記の例では全ファイルの名称とファイルサイズを 146 | 表示します。ただしフォルダを再帰的に展開したりはしません。 147 | 148 | 指定したフォルダを再帰的に展開したい場合には、Walk()を使います。WalkFunc()と同じ 149 | インターフェイスを持つ関数を指定すると、訪問先でその関数が実行されます。 150 | */ 151 | // import "path/filepath" 152 | // import "syscall" 153 | 154 | func dir_Glob() { 155 | 156 | // 再帰なし 157 | files, _ := filepath.Glob("/etc/*") 158 | for _, f := range files { 159 | printPathAndSize(f) 160 | } 161 | 162 | fmt.Println("---------") 163 | 164 | // 再帰あり 165 | filepath.Walk("/etc/", visit) 166 | 167 | } 168 | 169 | func visit(path string, info os.FileInfo, err error) error { 170 | 171 | printPathAndSize(path) 172 | return nil 173 | } 174 | 175 | func printPathAndSize(path string) { 176 | // ファイルサイズの取得 177 | var s syscall.Stat_t 178 | syscall.Stat(path, &s) 179 | 180 | fmt.Print(path) 181 | fmt.Print(": ") 182 | fmt.Print(s.Size) 183 | fmt.Println(" bytes") 184 | 185 | } 186 | 187 | //--------------------------------------------------- 188 | // ファイル名からディレクトリ部分だけを切り出す 189 | //--------------------------------------------------- 190 | /* 191 | os/filepathのDir()を使います。 192 | */ 193 | // import "os/filepath" 194 | 195 | func dir_DirName() { 196 | fmt.Println(filepath.Dir("/usr/bin/ruby")) // => "/usr/bin" 197 | fmt.Println(filepath.Dir("/etc/passwd")) // => "/etc" 198 | } 199 | 200 | //--------------------------------------------------- 201 | // ディレクトリかどうか判定する 202 | //--------------------------------------------------- 203 | /* 204 | os.Stat()でos.FileInfoが返ります。FileInfoのIsDir()で確認できます。 205 | 206 | シンボリックリンクかどうかなど、詳細情報が知りたい場合は、 207 | FileInfo.Mode()でFileModeが返るのでそちらを使います。 208 | */ 209 | // import "os" 210 | 211 | func dir_IsDir() { 212 | 213 | fInfo, _ := os.Stat("/etc") 214 | fmt.Println(fInfo.IsDir()) // => "true" 215 | } 216 | 217 | //--------------------------------------------------- 218 | // ディレクトリ内の全ファイルに対して処理を行う 219 | //--------------------------------------------------- 220 | /* 221 | [ワイルドカードにマッチしたファイル全てに処理を行う](#dir_Glob)参照のこと。 222 | */ 223 | 224 | //--------------------------------------------------- 225 | // ディレクトリ内の全ファイル名をフルパスで表示 226 | //--------------------------------------------------- 227 | 228 | /* 229 | [ワイルドカードにマッチしたファイル全てに処理を行う](#dir_Glob)と同様に、 230 | Walk()で可能です。 231 | */ 232 | // import "path/filepath" 233 | 234 | func dir_ShowFullPath() { 235 | filepath.Walk("/etc/", showFullPath) 236 | } 237 | 238 | func showFullPath(path string, info os.FileInfo, err error) error { 239 | fmt.Println(path) 240 | return nil 241 | } 242 | 243 | //--------------------------------------------------- 244 | // ディレクトリ 245 | //--------------------------------------------------- 246 | func Tips_file() { 247 | 248 | dir_MakeDir() // ディレクトリの作成 249 | dir_RemoveDir() // ディレクトリの削除 250 | dir_RemoveDirAll() // 中身が空でないディレクトリを削除する 251 | dir_Rename() // ディレクトリ名を変更する 252 | // ディレクトリの詳細情報を取得する 253 | // ディレクトリのファイルモードを変更する 254 | // ディレクトリの所有者とグループを変更する 255 | // ディレクトリの最終アクセス時刻と最終更新日時を変更する 256 | dir_Pwd() // カレントディレクトリの取得と変更 257 | dir_GetFileList() // ディレクトリ中のファイル一覧を取得する 258 | dir_Glob() // ワイルドカードにマッチしたファイル全てに処理を行う 259 | dir_DirName() // ファイル名からディレクトリ部分だけを切り出す 260 | dir_IsDir() // ディレクトリかどうか判定する 261 | // ディレクトリ内の全ファイルに対して処理を行う 262 | dir_ShowFullPath() // ディレクトリ内の全ファイル名をフルパスで表示 263 | 264 | } 265 | -------------------------------------------------------------------------------- /doc/html/github.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica, arial, sans-serif; 3 | font-size: 14px; 4 | line-height: 1.6; 5 | padding-top: 10px; 6 | padding-bottom: 10px; 7 | background-color: white; 8 | padding: 30px; } 9 | 10 | body > *:first-child { 11 | margin-top: 0 !important; } 12 | body > *:last-child { 13 | margin-bottom: 0 !important; } 14 | 15 | a { 16 | color: #4183C4; } 17 | a.absent { 18 | color: #cc0000; } 19 | a.anchor { 20 | display: block; 21 | padding-left: 30px; 22 | margin-left: -30px; 23 | cursor: pointer; 24 | position: absolute; 25 | top: 0; 26 | left: 0; 27 | bottom: 0; } 28 | 29 | h1, h2, h3, h4, h5, h6 { 30 | margin: 20px 0 10px; 31 | padding: 0; 32 | font-weight: bold; 33 | -webkit-font-smoothing: antialiased; 34 | cursor: text; 35 | position: relative; } 36 | 37 | h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor { 38 | background: url("../../images/modules/styleguide/para.png") no-repeat 10px center; 39 | text-decoration: none; } 40 | 41 | h1 tt, h1 code { 42 | font-size: inherit; } 43 | 44 | h2 tt, h2 code { 45 | font-size: inherit; } 46 | 47 | h3 tt, h3 code { 48 | font-size: inherit; } 49 | 50 | h4 tt, h4 code { 51 | font-size: inherit; } 52 | 53 | h5 tt, h5 code { 54 | font-size: inherit; } 55 | 56 | h6 tt, h6 code { 57 | font-size: inherit; } 58 | 59 | h1 { 60 | font-size: 28px; 61 | color: black; } 62 | 63 | h2 { 64 | font-size: 24px; 65 | border-bottom: 1px solid #cccccc; 66 | color: black; } 67 | 68 | h3 { 69 | font-size: 18px; } 70 | 71 | h4 { 72 | font-size: 16px; } 73 | 74 | h5 { 75 | font-size: 14px; } 76 | 77 | h6 { 78 | color: #777777; 79 | font-size: 14px; } 80 | 81 | p, blockquote, ul, ol, dl, li, table, pre { 82 | margin: 5px 0; } 83 | 84 | hr { 85 | background: transparent url("../../images/modules/pulls/dirty-shade.png") repeat-x 0 0; 86 | border: 0 none; 87 | color: #cccccc; 88 | height: 4px; 89 | padding: 0; } 90 | 91 | body > h2:first-child { 92 | margin-top: 0; 93 | padding-top: 0; } 94 | body > h1:first-child { 95 | margin-top: 0; 96 | padding-top: 0; } 97 | body > h1:first-child + h2 { 98 | margin-top: 0; 99 | padding-top: 0; } 100 | body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child { 101 | margin-top: 0; 102 | padding-top: 0; } 103 | 104 | a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 { 105 | margin-top: 0; 106 | padding-top: 0; } 107 | 108 | h1 p, h2 p, h3 p, h4 p, h5 p, h6 p { 109 | margin-top: 0; } 110 | 111 | li p.first { 112 | display: inline-block; } 113 | 114 | ul, ol { 115 | padding-left: 30px; } 116 | 117 | ul :first-child, ol :first-child { 118 | margin-top: 0; } 119 | 120 | ul :last-child, ol :last-child { 121 | margin-bottom: 0; } 122 | 123 | dl { 124 | padding: 0; } 125 | dl dt { 126 | font-size: 14px; 127 | font-weight: bold; 128 | font-style: italic; 129 | padding: 0; 130 | margin: 15px 0 5px; } 131 | dl dt:first-child { 132 | padding: 0; } 133 | dl dt > :first-child { 134 | margin-top: 0; } 135 | dl dt > :last-child { 136 | margin-bottom: 0; } 137 | dl dd { 138 | margin: 0 0 15px; 139 | padding: 0 15px; } 140 | dl dd > :first-child { 141 | margin-top: 0; } 142 | dl dd > :last-child { 143 | margin-bottom: 0; } 144 | 145 | blockquote { 146 | border-left: 4px solid #dddddd; 147 | padding: 0 15px; 148 | color: #777777; } 149 | blockquote > :first-child { 150 | margin-top: 0; } 151 | blockquote > :last-child { 152 | margin-bottom: 0; } 153 | 154 | table { 155 | padding: 0; } 156 | table tr { 157 | border-top: 1px solid #cccccc; 158 | background-color: white; 159 | margin: 0; 160 | padding: 0; } 161 | table tr:nth-child(2n) { 162 | background-color: #f8f8f8; } 163 | table tr th { 164 | font-weight: bold; 165 | border: 1px solid #cccccc; 166 | text-align: left; 167 | margin: 0; 168 | padding: 6px 13px; } 169 | table tr td { 170 | border: 1px solid #cccccc; 171 | text-align: left; 172 | margin: 0; 173 | padding: 6px 13px; } 174 | table tr th :first-child, table tr td :first-child { 175 | margin-top: 0; } 176 | table tr th :last-child, table tr td :last-child { 177 | margin-bottom: 0; } 178 | 179 | img { 180 | max-width: 100%; } 181 | 182 | span.frame { 183 | display: block; 184 | overflow: hidden; } 185 | span.frame > span { 186 | border: 1px solid #dddddd; 187 | display: block; 188 | float: left; 189 | overflow: hidden; 190 | margin: 13px 0 0; 191 | padding: 7px; 192 | width: auto; } 193 | span.frame span img { 194 | display: block; 195 | float: left; } 196 | span.frame span span { 197 | clear: both; 198 | color: #333333; 199 | display: block; 200 | padding: 5px 0 0; } 201 | span.align-center { 202 | display: block; 203 | overflow: hidden; 204 | clear: both; } 205 | span.align-center > span { 206 | display: block; 207 | overflow: hidden; 208 | margin: 13px auto 0; 209 | text-align: center; } 210 | span.align-center span img { 211 | margin: 0 auto; 212 | text-align: center; } 213 | span.align-right { 214 | display: block; 215 | overflow: hidden; 216 | clear: both; } 217 | span.align-right > span { 218 | display: block; 219 | overflow: hidden; 220 | margin: 13px 0 0; 221 | text-align: right; } 222 | span.align-right span img { 223 | margin: 0; 224 | text-align: right; } 225 | span.float-left { 226 | display: block; 227 | margin-right: 13px; 228 | overflow: hidden; 229 | float: left; } 230 | span.float-left span { 231 | margin: 13px 0 0; } 232 | span.float-right { 233 | display: block; 234 | margin-left: 13px; 235 | overflow: hidden; 236 | float: right; } 237 | span.float-right > span { 238 | display: block; 239 | overflow: hidden; 240 | margin: 13px auto 0; 241 | text-align: right; } 242 | 243 | code, tt { 244 | margin: 0 2px; 245 | padding: 0 5px; 246 | white-space: nowrap; 247 | border: 1px solid #eaeaea; 248 | background-color: #f8f8f8; 249 | border-radius: 3px; } 250 | 251 | pre code { 252 | margin: 0; 253 | padding: 0; 254 | white-space: pre; 255 | border: none; 256 | background: transparent; } 257 | 258 | .highlight pre { 259 | background-color: #f8f8f8; 260 | border: 1px solid #cccccc; 261 | font-size: 13px; 262 | line-height: 19px; 263 | overflow: auto; 264 | padding: 6px 10px; 265 | border-radius: 3px; } 266 | 267 | pre { 268 | background-color: #f8f8f8; 269 | border: 1px solid #cccccc; 270 | font-size: 13px; 271 | line-height: 19px; 272 | overflow: auto; 273 | padding: 6px 10px; 274 | border-radius: 3px; } 275 | pre code, pre tt { 276 | background-color: transparent; 277 | border: none; } 278 | -------------------------------------------------------------------------------- /doc/html/highlight.pack.js: -------------------------------------------------------------------------------- 1 | !function(e){"undefined"!=typeof exports?e(exports):(window.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return window.hljs}))}(function(e){function n(e){return e.replace(/&/gm,"&").replace(//gm,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){var n=(e.className+" "+(e.parentNode?e.parentNode.className:"")).split(/\s+/);return n=n.map(function(e){return e.replace(/^lang(uage)?-/,"")}),n.filter(function(e){return N(e)||/no(-?)highlight|plain|text/.test(e)})[0]}function i(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function o(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3==i.nodeType?a+=i.nodeValue.length:1==i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function u(e,r,a){function i(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset"}function u(e){l+=""}function c(e){("start"==e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g==e&&g.length&&g[0].offset==s);f.reverse().forEach(o)}else"start"==g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(a.substr(s))}function c(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,o){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):Object.keys(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\b\w+\b/,!0),o&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&o.tE&&(a.tE+=(a.e?"|":"")+o.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(i(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,o);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function s(e,t,a,i){function o(e,n){for(var t=0;t";return i+=e+'">',i+n+o}function d(){if(!L.k)return n(y);var e="",t=0;L.lR.lastIndex=0;for(var r=L.lR.exec(y);r;){e+=n(y.substr(t,r.index-t));var a=g(L,r);a?(B+=a[1],e+=p(a[0],n(r[0]))):e+=n(r[0]),t=L.lR.lastIndex,r=L.lR.exec(y)}return e+n(y.substr(t))}function h(){if(L.sL&&!w[L.sL])return n(y);var e=L.sL?s(L.sL,y,!0,M[L.sL]):l(y);return L.r>0&&(B+=e.r),"continuous"==L.subLanguageMode&&(M[L.sL]=e.top),p(e.language,e.value,!1,!0)}function b(){return void 0!==L.sL?h():d()}function v(e,t){var r=e.cN?p(e.cN,"",!0):"";e.rB?(k+=r,y=""):e.eB?(k+=n(t)+r,y=""):(k+=r,y=t),L=Object.create(e,{parent:{value:L}})}function m(e,t){if(y+=e,void 0===t)return k+=b(),0;var r=o(t,L);if(r)return k+=b(),v(r,t),r.rB?0:t.length;var a=u(L,t);if(a){var i=L;i.rE||i.eE||(y+=t),k+=b();do L.cN&&(k+=""),B+=L.r,L=L.parent;while(L!=a.parent);return i.eE&&(k+=n(t)),y="",a.starts&&v(a.starts,""),i.rE?0:t.length}if(f(t,L))throw new Error('Illegal lexeme "'+t+'" for mode "'+(L.cN||"")+'"');return y+=t,t.length||1}var E=N(e);if(!E)throw new Error('Unknown language: "'+e+'"');c(E);var R,L=i||E,M={},k="";for(R=L;R!=E;R=R.parent)R.cN&&(k=p(R.cN,"",!0)+k);var y="",B=0;try{for(var C,j,I=0;;){if(L.t.lastIndex=I,C=L.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}for(m(t.substr(I)),R=L;R.parent;R=R.parent)R.cN&&(k+="");return{r:B,value:k,language:e,top:L}}catch(S){if(-1!=S.message.indexOf("Illegal"))return{r:0,value:n(t)};throw S}}function l(e,t){t=t||x.languages||Object.keys(w);var r={r:0,value:n(e)},a=r;return t.forEach(function(n){if(N(n)){var t=s(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}}),a.language&&(r.second_best=a),r}function f(e){return x.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,x.tabReplace)})),x.useBR&&(e=e.replace(/\n/g,"
")),e}function g(e,n,t){var r=n?E[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n=a(e);if(!/no(-?)highlight|plain|text/.test(n)){var t;x.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):t=e;var r=t.textContent,i=n?s(n,r,!0):l(r),c=o(t);if(c.length){var p=document.createElementNS("http://www.w3.org/1999/xhtml","div");p.innerHTML=i.value,i.value=u(c,o(p),r)}i.value=f(i.value),e.innerHTML=i.value,e.className=g(e.className,n,i.language),e.result={language:i.language,re:i.r},i.second_best&&(e.second_best={language:i.second_best.language,re:i.second_best.r})}}function d(e){x=i(x,e)}function h(){if(!h.called){h.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,p)}}function b(){addEventListener("DOMContentLoaded",h,!1),addEventListener("load",h,!1)}function v(n,t){var r=w[n]=t(e);r.aliases&&r.aliases.forEach(function(e){E[e]=n})}function m(){return Object.keys(w)}function N(e){return w[e]||w[E[e]]}var x={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},w={},E={};return e.highlight=s,e.highlightAuto=l,e.fixMarkup=f,e.highlightBlock=p,e.configure=d,e.initHighlighting=h,e.initHighlightingOnLoad=b,e.registerLanguage=v,e.listLanguages=m,e.getLanguage=N,e.inherit=i,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="\\b(0[xX][a-fA-F0-9]+|(\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e});hljs.registerLanguage("go",function(e){var t={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer",constant:"true false iota nil",typename:"bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{aliases:["golang"],k:t,i:""golang" 27 | } 28 | 29 | //--------------------------------------------------- 30 | // 文字にマッチさせる 31 | //--------------------------------------------------- 32 | /* 33 | 文字列にマッチするかどうかを確認するには 34 | (*Regexp) MatchString() を使います。 35 | 使える正規表現は[RE2 Standard](https://github.com/google/re2/wiki/Syntax)とのことです。 36 | 37 | 正規表現などを記載する文字列リテラルにダブルクオーテーション(\")を使う場合はエスケープを忘れずに。 38 | 特殊文字を一切解釈しない「未加工文字列リテラル」はシングルクオーテーション(\')ではなく 39 | バッククォーテーション(\`)を使うので注意。シングルクオーテーションはrune(UTF8文字)を表す表記です。 40 | たとえば、数値マッチさせる場合には 41 | ``` 42 | r = regexp.MustCompile("\\d") // OK 43 | r = regexp.MustCompile(`\d`) // OK 44 | r = regexp.MustCompile('\d') // NG 45 | ``` 46 | のような表記を使います。基本はバッククォーテーションということでよいでしょう。 47 | */ 48 | //import "regexp" 49 | 50 | func regexp_Match() { 51 | r := regexp.MustCompile(`abc`) 52 | fmt.Println(r.MatchString("hello")) // => false 53 | fmt.Println(r.MatchString("hello abc")) // => true 54 | } 55 | 56 | //--------------------------------------------------- 57 | // 繰り返し文字とマッチさせる 58 | //--------------------------------------------------- 59 | /* 60 | \*,\+,\?などで繰り返しも対応できます。 61 | */ 62 | // import "regexp" 63 | 64 | func regexp_Repeat() { 65 | check_regexp(`a*c`, "abc") // => "true" 66 | check_regexp(`a*c`, "ac") // => "true" 67 | check_regexp(`a*c`, "aaaaaac") // => "true" 68 | check_regexp(`a*c`, "c") // => "true" 69 | check_regexp(`a*c`, "abccccc") // => "true" 70 | check_regexp(`a*c`, "abd") // => "false" 71 | 72 | check_regexp(`a+c`, "abc") // => "false" 73 | check_regexp(`a+c`, "ac") // => "true" 74 | check_regexp(`a+c`, "aaaaaac") // => "true" 75 | check_regexp(`a+c`, "c") // => "false" 76 | check_regexp(`a+c`, "abccccc") // => "false" 77 | check_regexp(`a+c`, "abd") // => "false" 78 | 79 | check_regexp(`a?c`, "abc") // => "true" 80 | check_regexp(`a?c`, "ac") // => "true" 81 | check_regexp(`a?c`, "aaaaaac") // => "true" 82 | check_regexp(`a?c`, "c") // => "true" 83 | check_regexp(`a?c`, "abccccc") // => "true" 84 | check_regexp(`a?c`, "abd") // => "false" 85 | } 86 | 87 | func check_regexp(reg, str string) { 88 | fmt.Println(regexp.MustCompile(reg).Match([]byte(str))) 89 | } 90 | 91 | //--------------------------------------------------- 92 | // 数字だけ・アルファベットだけとマッチさせる 93 | //--------------------------------------------------- 94 | // import "regexp" 95 | 96 | func regexp_NumAlpha() { 97 | check_regexp(`[ABZ]`, "A") // => "true" 98 | check_regexp(`[ABZ]`, "Z") // => "true" 99 | check_regexp(`[ABZ]`, "Q") // => "false" 100 | 101 | check_regexp(`[0-9]`, "5") // => "true" 102 | check_regexp(`[0-9]`, "A") // => "false" 103 | check_regexp(`[A-Z]`, "A") // => "true" 104 | check_regexp(`[A-Z]`, "5") // => "false" 105 | check_regexp(`[A-Z]`, "a") // => "false" 106 | 107 | check_regexp(`[^0-9]`, "A") // => "true" 108 | check_regexp(`[^0-9]`, "5") // => "false" 109 | } 110 | 111 | //func check_regexp(reg, str string) { 112 | // fmt.Println(regexp.MustCompile(reg).Match([]byte(str))) 113 | //} 114 | 115 | //--------------------------------------------------- 116 | // 改行コードを含む文字列にマッチさせる 117 | //--------------------------------------------------- 118 | /* 119 | 改行コードを含む複数ラインに対するマッチを行うには、 120 | 正規表現の冒頭に`(?m)`と書くことで対応できます。 121 | */ 122 | // import "regexp" 123 | 124 | func regexp_MultiLine() { 125 | txt := "hello,\nworld" 126 | check_regexp(`(?m)^(w.*)$`, txt) 127 | } 128 | 129 | //func check_regexp(reg, str string) { 130 | // fmt.Println(regexp.MustCompile(reg).Match([]byte(str))) 131 | //} 132 | 133 | //--------------------------------------------------- 134 | // 正規表現を使って文字列を置き換える 135 | //--------------------------------------------------- 136 | /* 137 | ReplaceAllString()を使います。 138 | */ 139 | // import "regexp" 140 | 141 | func regexp_Replace() { 142 | str := "Copyright 2015 by ASHITANI Tatsuji." 143 | rep := regexp.MustCompile(`[A-Za-z]*right`) 144 | str = rep.ReplaceAllString(str, "Copyleft") 145 | 146 | fmt.Println(str) // => "Copyleft 2015 by ASHITANI Tatsuji." 147 | } 148 | 149 | //--------------------------------------------------- 150 | // n番めのマッチを見つける 151 | //--------------------------------------------------- 152 | /* 153 | 見つけたグループを指定しつつ置換をしたい場合は`$1`などを使います。 154 | */ 155 | // import "regexp" 156 | 157 | func regexp_Numbering() { 158 | str := "123456" 159 | rep := regexp.MustCompile(`1(.)3(.)5(.)`) 160 | str = rep.ReplaceAllString(str, "1($1)3($2)5($3)") 161 | 162 | fmt.Println(str) // => "1(2)3(4)5(6)" 163 | } 164 | 165 | //--------------------------------------------------- 166 | // パターンで区切られたレコードを読む 167 | //--------------------------------------------------- 168 | /* 169 | Split(s string, n int)を使います。nは回数指定で、負を指定すれば全て行います。 170 | */ 171 | // import "regexp" 172 | 173 | func regexp_Split() { 174 | str := "001,ASHITANI Tatsuji, Yokohama" 175 | rep := regexp.MustCompile(`\s*,\s*`) 176 | result := rep.Split(str, -1) 177 | 178 | fmt.Println(result[0]) // = >"001" 179 | fmt.Println(result[1]) // = >"ASHITANI Tatsuji" 180 | fmt.Println(result[2]) // = >"Yokohama" 181 | } 182 | 183 | //--------------------------------------------------- 184 | // マッチした文字列を全て抜き出して配列へ格納する 185 | //--------------------------------------------------- 186 | /* 187 | FindAllStringSubmatch()を使います。 188 | 189 | グルーピングを指定すると、[[マッチ全体, 1つ目のグループ、2つめのグループ、、], ...] 190 | のようなスライスが返ります。 191 | */ 192 | // import "regexp" 193 | 194 | func regexp_FindAll() { 195 | s := "hoge:0045-111-2222 boke:0045-222-2222" 196 | r := regexp.MustCompile(`[\d\-]+`) 197 | fmt.Println(r.FindAllStringSubmatch(s, -1)) // => "[[0045-111-2222] [0045-222-2222]]" 198 | 199 | r2 := regexp.MustCompile(`(\S+):([\d\-]+)`) 200 | 201 | result := r2.FindAllStringSubmatch(s, -1) 202 | fmt.Println(result[0]) // => "[hoge:0045-111-2222 hoge 0045-111-2222]" 203 | fmt.Println(result[1]) // => "[boke:0045-222-2222 boke 0045-222-2222]" 204 | } 205 | 206 | //--------------------------------------------------- 207 | // 正規表現にコメントを付ける 208 | //--------------------------------------------------- 209 | /* 210 | rubyには正規表現を見やすくするxオプションがありますが、golangにはなさそうなので、 211 | 自前で実装します。といっても空白とコメントを削除するだけですが。 212 | 213 | */ 214 | // import "regexp" 215 | 216 | func regexp_Comment() { 217 | r := `(\S+): # 名前 218 | ([\d\-]+) # 電話番号 219 | ` 220 | str := "hoge:0045-111-2222 boke:0045-222-2222" 221 | result := find_x(r, str) 222 | fmt.Println(result[0]) // => "[hoge:0045-111-2222 hoge 0045-111-2222]" 223 | fmt.Println(result[1]) // => "[boke:0045-222-2222 boke 0045-222-2222]" 224 | } 225 | 226 | func find_x(r, str string) [][]string { 227 | com := regexp.MustCompile(`(?m)(\s+)|(\#.*$)`) 228 | r = com.ReplaceAllString(r, "") 229 | reg := regexp.MustCompile(r) 230 | return reg.FindAllStringSubmatch(str, -1) 231 | } 232 | 233 | //--------------------------------------------------- 234 | // 正規表現内でString型変数を使う 235 | //--------------------------------------------------- 236 | /* 237 | Rubyと違って正規表現リテラルがあるわけではないので、 238 | stringを編集してcompile()です。 239 | */ 240 | // import "regexp" 241 | 242 | func regexp_String() { 243 | regEx := `^a` 244 | reg := regexp.MustCompile(regEx) 245 | fmt.Println(reg.FindAllStringSubmatch("abc", -1)) // =>[[a]] 246 | } 247 | 248 | //--------------------------------------------------- 249 | // 正規表現(パターンマッチ) 250 | //--------------------------------------------------- 251 | func Tips_regexp() { 252 | regexp_Regexp() // 正規表現を使う 253 | regexp_Match() // 文字にマッチさせる 254 | regexp_Repeat() // 繰り返し文字とマッチさせる 255 | regexp_NumAlpha() // 数字だけ・アルファベットだけとマッチさせる 256 | regexp_MultiLine() // 改行コードを含む文字列にマッチさせる 257 | regexp_Replace() // 正規表現を使って文字列を置き換える 258 | regexp_Numbering() // n番めのマッチを見つける 259 | regexp_Split() // パターンで区切られたレコードを読む 260 | regexp_FindAll() // マッチした文字列を全て抜き出して配列へ格納する 261 | regexp_Comment() // 正規表現にコメントを付ける 262 | regexp_String() // 正規表現内でString型変数を使う 263 | 264 | } 265 | -------------------------------------------------------------------------------- /pkg/tips_goroutine/tips_goroutine.go: -------------------------------------------------------------------------------- 1 | /* 2 | goroutine 3 | */ 4 | 5 | package tips_dir 6 | 7 | import ( 8 | "fmt" 9 | "github.com/tlorens/go-ibgetkey" 10 | "io/ioutil" 11 | "math" 12 | "os" 13 | "runtime/pprof" 14 | "strconv" 15 | "sync" 16 | "time" 17 | ) 18 | 19 | //--------------------------------------------------- 20 | // goroutineを生成する 21 | //--------------------------------------------------- 22 | /* 23 | goroutineはスレッドのようなものです。 24 | 25 | joinはないので、終了を待つ場合はchannelを使います。 26 | ``` 27 | <-quit 28 | ``` 29 | とすると、quitというchannelに値が書き込まれるまで待ちます。 30 | 31 | 私の環境では、 32 | ``` 33 | Create goroutine 34 | Waiting for the goroutine to complete 35 | Start goroutine 36 | End goroutine 37 | Test compleated 38 | ``` 39 | という順番で表示されました。WaitingとStartの順番が直感と合いませんが、 40 | goroutineの起動にオーバヘッドがあるのでしょうかね。 41 | */ 42 | // import "time" 43 | 44 | func goroutine_Create() { 45 | fmt.Println("Create goroutine") 46 | quit := make(chan bool) 47 | go func() { 48 | fmt.Println("Start goroutine") 49 | time.Sleep(3 * time.Second) 50 | fmt.Println("End goroutine") 51 | quit <- true 52 | }() 53 | fmt.Println("Waiting for the goroutine to complete") 54 | <-quit 55 | fmt.Println("Test compleated") 56 | } 57 | 58 | //--------------------------------------------------- 59 | // goroutineに引数を渡す 60 | //--------------------------------------------------- 61 | /* 62 | goroutineは外部宣言したfuncでも起動できます。 63 | channelが必要な場合は引数にchannelを渡します。 64 | もちろん、channel以外の引数も渡すことができます。 65 | ``` 66 | Start goroutine - Apple 10 67 | ``` 68 | と表示されます。 69 | */ 70 | //import "time" 71 | 72 | func goroutine_Argument() { 73 | fmt.Println("Test start") 74 | fmt.Println("Create goroutine") 75 | 76 | quit := make(chan bool) 77 | go appleGoroutine("Apple", 10, quit) 78 | fmt.Println("Waiting for the goroutine to complete") 79 | <-quit 80 | fmt.Println("Test compleated") 81 | } 82 | 83 | func appleGoroutine(fruit string, a int, quit chan bool) { 84 | fmt.Printf("Start goroutine - %s %d\n", fruit, a) 85 | time.Sleep(3 * time.Second) 86 | fmt.Println("End goroutine") 87 | quit <- true 88 | } 89 | 90 | //--------------------------------------------------- 91 | // goroutineの終了を待つ 92 | //--------------------------------------------------- 93 | /* 94 | 終了待ちはchannelの受信で行います。[goroutineを生成する](#goroutine_Create) 95 | を参照してください。 96 | */ 97 | 98 | //--------------------------------------------------- 99 | // goroutineの実行を終了させる 100 | //--------------------------------------------------- 101 | /* 102 | スレッドと違ってgoroutineは外部から終了させることは出来ません。 103 | チャネルをつかって無限ループを抜けるようにするのが一案です。 104 | 無限ループを抜ける際に、breakにラベルを与えてどの階層まで抜けるかを指示できるようです。 105 | 106 | 下記のプログラムはGorutine内で"."を100msec置きに50回表示して終了しますが、 107 | "."を押すとGorutineを途中で終了します。終了の意思を伝えるためにkillというチャネルで 108 | 通信を行っています。 109 | 110 | なお、一文字入力を受け付けるのに 111 | [go-ibgetkey](https://github.com/tlorens/go-ibgetkey)という 112 | ライブラリを使いました。 113 | */ 114 | // import "github.com/tlorens/go-ibgetkey" 115 | // import "time" 116 | 117 | func goroutine_Kill() { 118 | kill := make(chan bool) 119 | finished := make(chan bool) 120 | go killableGoroutine(kill, finished) 121 | targetkey := "." 122 | t := int(targetkey[0]) 123 | loop: 124 | for { 125 | input := keyboard.ReadKey() 126 | select { 127 | case <-finished: 128 | break loop 129 | default: 130 | if input == t { 131 | kill <- true 132 | break loop 133 | } 134 | } 135 | } 136 | } 137 | 138 | func killableGoroutine(kill, finished chan bool) { 139 | fmt.Println("Started goroutine. Push \".\" to kill me.") 140 | for i := 0; i < 50; i++ { 141 | select { 142 | case <-kill: 143 | fmt.Println() 144 | fmt.Println("Killed") 145 | finished <- true 146 | return 147 | default: 148 | fmt.Print(".") 149 | time.Sleep(100 * time.Millisecond) 150 | } 151 | } 152 | fmt.Println() 153 | fmt.Println("Finished..push any key to abort.") 154 | finished <- true 155 | return 156 | } 157 | 158 | //--------------------------------------------------- 159 | // goroutineを停止する 160 | //--------------------------------------------------- 161 | /* 162 | [goroutineの実行を終了させる](#goroutine_)と同様にchannelで通信を行います。 163 | 164 | 下記のプログラムはGorutine内で"."を100msec置きに50回表示して終了しますが、 165 | "."を入力するとGorutineを途中で停止・再開します。 166 | */ 167 | // import "github.com/tlorens/go-ibgetkey" 168 | // import "time" 169 | 170 | func goroutine_Stop() { 171 | com := make(chan string) 172 | finished := make(chan bool) 173 | go stoppableGoroutine(com, finished) 174 | targetkey := "." 175 | t := int(targetkey[0]) 176 | running := true 177 | loop: 178 | for { 179 | input := keyboard.ReadKey() 180 | select { 181 | case <-finished: 182 | break loop 183 | default: 184 | if input == t { 185 | if running == true { 186 | com <- "stop" 187 | running = false 188 | } else { 189 | com <- "start" 190 | running = true 191 | } 192 | } 193 | } 194 | } 195 | } 196 | 197 | func stoppableGoroutine(command chan string, finished chan bool) { 198 | fmt.Println("Started goroutine. Push \".\" to stop/start me.") 199 | running := true 200 | i := 0 201 | for i < 50 { 202 | select { 203 | case com := <-command: 204 | if com == "stop" { 205 | running = false 206 | } else { 207 | running = true 208 | } 209 | default: 210 | } 211 | if running == true { 212 | fmt.Print(".") 213 | time.Sleep(100 * time.Millisecond) 214 | i++ 215 | } 216 | } 217 | fmt.Println() 218 | fmt.Println("Finished..push any key to abort.") 219 | finished <- true 220 | return 221 | } 222 | 223 | //--------------------------------------------------- 224 | // 実行中のgoroutine一覧を取得する 225 | //--------------------------------------------------- 226 | /* 227 | Ruby版ではリストを出してそれぞれをkillするというプログラムでしたが、 228 | そもそもkillを簡単に実装する方法がないので、リスト表示だけにとどめます。 229 | goroutineをリスト化する関数自体やmain関数自身もgoroutineなので 230 | 多数のgoroutineが表示されます。 231 | */ 232 | //import "os" 233 | //import "runtime/pprof" 234 | //import "time" 235 | 236 | func goroutine_ListGoroutines() { 237 | go goroutine1() 238 | go goroutine2() 239 | 240 | time.Sleep(1 * time.Second) // goroutineの起動のオーバヘッド待ち 241 | pprof.Lookup("goroutine").WriteTo(os.Stdout, 2) // 2はデバッグレベル。goroutineだけリストする、の意味。 242 | } 243 | 244 | func goroutine1() { 245 | time.Sleep(5 * time.Second) 246 | fmt.Println("Goroutine1 finished") 247 | } 248 | 249 | func goroutine2() { 250 | time.Sleep(5 * time.Second) 251 | fmt.Println("Goroutine2 finished") 252 | } 253 | 254 | //--------------------------------------------------- 255 | // goroutine間で通信する 256 | //--------------------------------------------------- 257 | /* 258 | Ruby版ではQueueを使っているところを、channelに変更します。 259 | makeでchannelの深さを指定しますが、深さ以上に値を突っ込もうとすると 260 | その時点でロックします。[こちら](http://rosylilly.hatenablog.com/entry/2013/09/26/124801)をご参考。 261 | 262 | 下記プログラムはキー入力を受付け、平方根を返します。-1を入力すると終了します。 263 | */ 264 | // import "math" 265 | 266 | func goroutine_Com() { 267 | queue := make(chan int, 3) // 3はキューの深さ 268 | go sqrtGoroutine(queue) 269 | 270 | line := 0 271 | loop: 272 | for { 273 | fmt.Scanln(&line) 274 | if line == -1 { 275 | break loop 276 | } else { 277 | queue <- line 278 | } 279 | } 280 | } 281 | 282 | func sqrtGoroutine(queue chan int) { 283 | for { 284 | n := <-queue 285 | if int(n) >= 0 { 286 | val := math.Sqrt(float64(n)) 287 | fmt.Printf("Square(%d) = %f\n", int(n), val) 288 | } else { 289 | fmt.Println("?") 290 | } 291 | } 292 | } 293 | 294 | //--------------------------------------------------- 295 | // goroutine間の競合を回避する(Mutex) 296 | //--------------------------------------------------- 297 | /* 298 | syncパッケージにMutexがあります。複数のgoroutine終了を待つにはWaitGroupを使います。 299 | [こちら](http://mattn.kaoriya.net/software/lang/go/20140625223125.htm)がよくまとまっています。 300 | 301 | ファイルcount.txtを作って0を書き込み、gotoutine内ではファイルの数値を読んでインクリメントして書き戻します。 302 | 終了後は、goroutineが10個走るのでcount.txtの値は10になっています。 303 | */ 304 | //import "sync" 305 | //import "io/ioutil" 306 | 307 | func goroutine_Mutex() { 308 | wg := new(sync.WaitGroup) 309 | m := new(sync.Mutex) 310 | write(0) 311 | 312 | for i := 0; i < 10; i++ { 313 | wg.Add(1) 314 | go countupGoroutine(wg, m) 315 | } 316 | wg.Wait() 317 | } 318 | 319 | func countupGoroutine(wg *sync.WaitGroup, m *sync.Mutex) { 320 | m.Lock() 321 | defer m.Unlock() 322 | counter := read() + 1 323 | write(counter) 324 | wg.Done() 325 | } 326 | 327 | func write(i int) { 328 | s := strconv.Itoa(i) 329 | ioutil.WriteFile("count.txt", []byte(s), os.ModePerm) 330 | } 331 | 332 | func read() int { 333 | t, _ := ioutil.ReadFile("count.txt") 334 | i, _ := strconv.Atoi(string(t)) 335 | return i 336 | } 337 | 338 | //--------------------------------------------------- 339 | // goroutine 340 | //--------------------------------------------------- 341 | func Tips_goroutine() { 342 | goroutine_Create() // goroutineを生成する 343 | goroutine_Argument() // goroutineに引数を渡す 344 | // goroutineの終了を待つ 345 | goroutine_Kill() // goroutineの実行を終了させる 346 | goroutine_Stop() // goroutineを停止する 347 | goroutine_ListGoroutines() // 実行中のgoroutine一覧を取得する 348 | goroutine_Com() // goroutine間で通信する 349 | goroutine_Mutex() // goroutine間の競合を回避する(Mutex) 350 | 351 | } 352 | -------------------------------------------------------------------------------- /pkg/tips_map/tips_map.go: -------------------------------------------------------------------------------- 1 | /* 2 | マップ(ハッシュ) 3 | */ 4 | 5 | package tips_map 6 | 7 | import ( 8 | "fmt" 9 | "math/rand" 10 | "sort" 11 | "time" 12 | ) 13 | 14 | //--------------------------------------------------- 15 | //プログラム中でマップを定義する 16 | //--------------------------------------------------- 17 | /* 18 | Golangではハッシュ(連想配列)のことをmapと呼びます。 19 | */ 20 | func map_Map() { 21 | m := map[string]int{"apple": 150, "banana": 300, "lemon": 300} 22 | fmt.Println(m) // => "map[apple:150 banana:300 lemon:300]" 23 | } 24 | 25 | //--------------------------------------------------- 26 | //キーに関連付けられた値を取得する 27 | //--------------------------------------------------- 28 | /* 29 | マップ[キー]でキーに関連した値を取得できます。 30 | 31 | 未定義のキーを渡すとゼロ(int型の場合は0)が返ります。 32 | ``` 33 | v, ok:=マップ[キー] 34 | ``` 35 | で未定義かどうか確認できます。 36 | */ 37 | func map_Get() { 38 | m := map[string]int{"apple": 150, "banana": 300, "lemon": 300} 39 | 40 | fmt.Println(m["apple"]) // => "150" 41 | fmt.Println(m["banana"]) // => "300" 42 | fmt.Println(m["lemon"]) // => "300" 43 | fmt.Println(m["papaia"]) // => "0" 44 | 45 | v, ok := m["apple"] 46 | fmt.Println(v) // => "150" 47 | fmt.Println(ok) // => "true" 48 | 49 | v, ok = m["papaia"] 50 | fmt.Println(v) // => "0" 51 | fmt.Println(ok) // => "false" 52 | } 53 | 54 | //--------------------------------------------------- 55 | //マップに要素を追加する 56 | //--------------------------------------------------- 57 | /* 58 | 空のマップを作るのは下記のような書き方があります。 59 | */ 60 | func map_Add() { 61 | m := map[string]int{} 62 | //m := make(map[string]int) 63 | 64 | m["apple"] = 150 65 | m["banana"] = 200 66 | m["lemon"] = 300 67 | 68 | fmt.Println(m["apple"]) 69 | } 70 | 71 | //--------------------------------------------------- 72 | //マップ内にキーが存在するかどうか調べる 73 | //--------------------------------------------------- 74 | /* 75 | _, ok = マップ[キー]でokの値を見るのが良さそうです。 76 | */ 77 | 78 | func map_HasKey() { 79 | 80 | m := map[string]int{"apple": 150, "banana": 300, "lemon": 300} 81 | 82 | _, ok := m["apple"] 83 | fmt.Println(ok) // => "true" 84 | _, ok = m["orange"] 85 | fmt.Println(ok) // => "false" 86 | 87 | } 88 | 89 | //--------------------------------------------------- 90 | //マップの要素数を取得する 91 | //--------------------------------------------------- 92 | /* 93 | len(マップ)で求められます。 94 | */ 95 | func map_Length() { 96 | m := map[string]int{"apple": 150, "banana": 300, "lemon": 300} 97 | 98 | fmt.Println(len(m)) 99 | } 100 | 101 | //--------------------------------------------------- 102 | //キーが存在しない場合のデフォルト値を設定する 103 | //--------------------------------------------------- 104 | /* 105 | デフォルトはあくまで0のようですので、新しい型を作るのがよさそうです。 106 | */ 107 | func map_Default() { 108 | m := map[string]int{"apple": 150, "banana": 300, "lemon": 300} 109 | dm := dmap{m} 110 | 111 | fmt.Println(dm.Get("apple")) // => "300" 112 | fmt.Println(dm.Get("papaia")) // => "100" 113 | } 114 | 115 | type dmap struct { 116 | m map[string]int 117 | } 118 | 119 | func (d dmap) Get(key string) int { 120 | v, ok := d.m[key] 121 | if ok { 122 | return v 123 | } else { 124 | return 100 // default 125 | } 126 | } 127 | 128 | func (d dmap) Set(key string, value int) { 129 | d.m[key] = value 130 | } 131 | 132 | //--------------------------------------------------- 133 | //マップからエントリを削除する 134 | //--------------------------------------------------- 135 | /* 136 | delete(マップ,キー)でエントリを削除できます。 137 | rubyのように削除エントリを戻り値に返したりブロックを返したりは 138 | なさそうですので、匿名関数を作って渡す関数を書きます。 139 | */ 140 | func map_Delete() { 141 | // 消去 142 | m := map[string]int{"apple": 150, "banana": 300} 143 | delete(m, "banana") 144 | 145 | // 存在しないときはエラーを表示 146 | f := func(k string) { 147 | fmt.Printf("%s not found\n", k) 148 | } 149 | delete_if_exist(m, "banana", f) // => "banana not found" 150 | fmt.Println(m) // => "map[apple:150]" 151 | 152 | // 200より小さい値を持つエントリを削除 153 | m = map[string]int{"apple": 150, "banana": 300, "lemon": 400} 154 | f_small := func(m map[string]int, k string) bool { 155 | return (m[k] < 200) 156 | } 157 | delete_if(m, f_small) 158 | fmt.Println(m) // => "map[banana:300 lemon:400]" 159 | 160 | } 161 | 162 | // 指定したキーが存在しなければf()を実行 163 | func delete_if_exist(m map[string]int, k string, f func(string)) int { 164 | v, ok := m[k] 165 | 166 | if ok { 167 | delete(m, k) 168 | return v 169 | } else { 170 | f(k) 171 | return 0 172 | } 173 | } 174 | 175 | // func_if()がtrueの場合は対象を消す 176 | func delete_if( 177 | m map[string]int, 178 | func_if func(map[string]int, string) bool, 179 | ) { 180 | for k := range m { 181 | ok := func_if(m, k) 182 | if ok { 183 | delete(m, k) 184 | } else { 185 | } 186 | } 187 | } 188 | 189 | //--------------------------------------------------- 190 | //マップの全エントリに対してブロックを実行する 191 | //--------------------------------------------------- 192 | /* 193 | ``` 194 | for key, value := range m { 195 | } 196 | ``` 197 | でkey,valueを取り出しつつエントリを走査できます。 198 | */ 199 | 200 | func map_Block() { 201 | m := map[string]int{"apple": 150, "banana": 300, "lemon": 300} 202 | 203 | sum := 0 204 | fruits := []string{} 205 | for k, v := range m { 206 | fruits = append(fruits, k) 207 | sum += v 208 | } 209 | fmt.Println(fruits) // => "[apple banana lemon]" 210 | fmt.Println(sum) // => "750" 211 | } 212 | 213 | //--------------------------------------------------- 214 | //マップを配列に変換する 215 | //--------------------------------------------------- 216 | /* 217 | rubyのkeys(), values(), to_a(), indexes() はすべて 218 | range()で実装できます。 219 | */ 220 | func map_ToArray() { 221 | m := map[string]int{"apple": 150, "banana": 300, "lemon": 300} 222 | fmt.Println(keys(m)) // => "[apple banana lemon]" 223 | fmt.Println(values(m)) // => "[150 300 300]" 224 | fmt.Println(to_a(m)) // => "[[lemon 300] [apple 150] [banana 300]]" 225 | 226 | keys := []string{"apple", "lemon"} 227 | fmt.Println(indexes(m, keys)) // => "[150 300]" 228 | 229 | } 230 | 231 | func keys(m map[string]int) []string { 232 | ks := []string{} 233 | for k, _ := range m { 234 | ks = append(ks, k) 235 | } 236 | return ks 237 | } 238 | 239 | func values(m map[string]int) []int { 240 | vs := []int{} 241 | for _, v := range m { 242 | vs = append(vs, v) 243 | } 244 | return vs 245 | } 246 | 247 | func to_a(m map[string]int) []interface{} { 248 | a := []interface{}{} 249 | for k, v := range m { 250 | a = append(a, []interface{}{k, v}) 251 | } 252 | return a 253 | } 254 | 255 | func indexes(m map[string]int, keys []string) []int { 256 | vs := []int{} 257 | for _, k := range keys { 258 | vs = append(vs, m[k]) 259 | } 260 | return vs 261 | } 262 | 263 | //--------------------------------------------------- 264 | //マップを空にする 265 | //--------------------------------------------------- 266 | /* 267 | 再初期化するのが早そうです。 268 | m=nilでも一見クリアできるのですが、再代入できなくなります。 269 | */ 270 | func map_Clear() { 271 | m := map[string]int{"apple": 150, "banana": 300, "lemon": 300} 272 | m = make(map[string]int) 273 | fmt.Println(m) 274 | } 275 | 276 | //--------------------------------------------------- 277 | //マップを値で降順、値が等しい場合キーで昇順にソートする 278 | //--------------------------------------------------- 279 | /* 280 | [条件式を指定したソート](http://ashitani.jp/golangtips/tips_slice.html#slice_Sort) 281 | と同様のことを行います。 282 | */ 283 | // import "sort" 284 | func map_Sort() { 285 | m := map[string]int{"ada": 1, "hoge": 4, "basha": 3, "poeni": 3} 286 | 287 | a := List{} 288 | for k, v := range m { 289 | e := Entry{k, v} 290 | a = append(a, e) 291 | } 292 | 293 | sort.Sort(a) 294 | fmt.Println(a) 295 | } 296 | 297 | type Entry struct { 298 | name string 299 | value int 300 | } 301 | type List []Entry 302 | 303 | func (l List) Len() int { 304 | return len(l) 305 | } 306 | 307 | func (l List) Swap(i, j int) { 308 | l[i], l[j] = l[j], l[i] 309 | } 310 | 311 | func (l List) Less(i, j int) bool { 312 | if l[i].value == l[j].value { 313 | return (l[i].name < l[j].name) 314 | } else { 315 | return (l[i].value < l[j].value) 316 | } 317 | } 318 | 319 | //--------------------------------------------------- 320 | //マップの要素をランダムに抽出する 321 | //--------------------------------------------------- 322 | /* 323 | うーん、range()に頼りますか。 324 | 325 | 乱数は[擬似乱数を生成する](http://ashitani.jp/golangtips/tips_num.html#num_Rand) 326 | にあります。 327 | */ 328 | // import "math/rand" 329 | // import "time" 330 | func map_Random() { 331 | m := map[string]int{"apple": 150, "banana": 300, "lemon": 300} 332 | 333 | rand.Seed(time.Now().UnixNano()) //Seed 334 | 335 | fmt.Println(choice(m)) 336 | fmt.Println(choice(m)) 337 | fmt.Println(choice(m)) 338 | fmt.Println(choice(m)) 339 | 340 | } 341 | 342 | func choice(m map[string]int) string { 343 | l := len(m) 344 | i := 0 345 | 346 | index := rand.Intn(l) 347 | 348 | ans := "" 349 | for k, _ := range m { 350 | if index == i { 351 | ans = k 352 | break 353 | } else { 354 | i++ 355 | } 356 | } 357 | return ans 358 | } 359 | 360 | //--------------------------------------------------- 361 | //複数のマップをマージする 362 | //--------------------------------------------------- 363 | func map_Merge() { 364 | m1 := map[string]string{"key1": "val1", "key2": "val2"} 365 | m2 := map[string]string{"key3": "val3"} 366 | 367 | fmt.Println(merge(m1, m2)) // => "map[val1:key1 val2:key2 val3:key3]" 368 | } 369 | 370 | func merge(m1, m2 map[string]string) map[string]string { 371 | ans := map[string]string{} 372 | 373 | for k, v := range m1 { 374 | ans[k] = v 375 | } 376 | for k, v := range m2 { 377 | ans[k] = v 378 | } 379 | return (ans) 380 | } 381 | 382 | //--------------------------------------------------- 383 | // マップ(ハッシュ) 384 | //--------------------------------------------------- 385 | func Tips_map() { 386 | map_Map() // プログラム中でマップを定義する 387 | map_Get() // キーに関連付けられた値を取得する 388 | map_Add() // マップに要素を追加する 389 | map_HasKey() // マップ内にキーが存在するかどうか調べる 390 | map_Length() // マップの要素数を取得する 391 | map_Default() // キーが存在しない場合のデフォルト値を設定する 392 | map_Delete() // マップからエントリを削除する 393 | map_Block() // マップの全エントリに対してブロックを実行する 394 | map_ToArray() // マップを配列に変換する 395 | map_Clear() // マップを空にする 396 | map_Sort() // マップを値で降順、値が等しい場合キーで昇順にソートする 397 | map_Random() // マップの要素をランダムに抽出する 398 | map_Merge() // 複数のマップをマージする 399 | } 400 | -------------------------------------------------------------------------------- /pkg/tips_time/tips_time.go: -------------------------------------------------------------------------------- 1 | /* 2 | 日付と時刻 3 | */ 4 | 5 | package tips_time 6 | 7 | import ( 8 | "fmt" 9 | "time" 10 | ) 11 | 12 | //--------------------------------------------------- 13 | // 現在の時刻を取得する 14 | //--------------------------------------------------- 15 | //import "time" 16 | 17 | func time_Now() { 18 | t := time.Now() 19 | fmt.Println(t) // => "2015-05-05 07:23:30.757800829 +0900 JST" 20 | fmt.Println(t.Year()) // => "2015" 21 | fmt.Println(t.Month()) // => "May" 22 | fmt.Println(t.Day()) // => "5" 23 | fmt.Println(t.Hour()) // => "7" 24 | fmt.Println(t.Minute()) // => "23" 25 | fmt.Println(t.Second()) // => "30" 26 | fmt.Println(t.Weekday()) // => "Tuesday" 27 | } 28 | 29 | //--------------------------------------------------- 30 | // 時刻オブジェクトを作成する 31 | //--------------------------------------------------- 32 | /* 秒の後にナノセカンドまで指定するのを忘れがちなので注意。*/ 33 | //import "time" 34 | 35 | func time_Make() { 36 | t := time.Date(2001, 5, 20, 23, 59, 59, 0, time.UTC) 37 | fmt.Println(t) // => "2001-05-20 23:59:59 +0000 UTC" 38 | t = time.Date(2001, 5, 20, 23, 59, 59, 0, time.Local) 39 | fmt.Println(t) // => "2001-05-20 23:59:59 +0900 JST" 40 | } 41 | 42 | //--------------------------------------------------- 43 | // 時刻を任意のフォーマットで扱う 44 | //--------------------------------------------------- 45 | /* 46 | time.FormatはrubyのTime::strftimeと違い、 47 | %Hなどの制御文字で行うのではなく例文で書きます。 48 | 49 | "Mon Jan 2 15:04:05 -0700 MST 2006" 50 | 51 | を並べ替える仕様のようです。なんでこの時刻?ってのは 52 | [こちら](http://qiita.com/ruiu/items/5936b4c3bd6eb487c182) 53 | にありました。 54 | */ 55 | //import "time" 56 | 57 | func time_Format() { 58 | t := time.Now() 59 | const layout = "Now, Monday Jan 02 15:04:05 JST 2006" 60 | fmt.Println(t.Format(layout)) // => "Now, Tuesday May 05 07:53:54 JST 2015" 61 | const layout2 = "2006-01-02 15:04:05" 62 | fmt.Println(t.Format(layout2)) // => "2015-05-05 07:53:54" 63 | 64 | } 65 | 66 | //--------------------------------------------------- 67 | // 時刻オブジェクトを文字列に変換する 68 | //--------------------------------------------------- 69 | //import "time" 70 | 71 | func time_ToString() { 72 | t := time.Now() 73 | s := "" 74 | s = t.String() 75 | fmt.Println(s) // => "2015-05-05 08:05:15.828452891 +0900 JST" 76 | } 77 | 78 | //--------------------------------------------------- 79 | // 時刻に任意の時間を加減する 80 | //--------------------------------------------------- 81 | /* 82 | 時間差を表現する型はtime.Durationで、単位はナノ秒です。 83 | time.Second,time.Hour等を掛け算することで秒単位、時間単位を表現します。 84 | 85 | あるいはtime.ParseDuration("100s")などで生成するのも便利です。 86 | 87 | 減算したい場合は負の値をAdd()すればよいです。 88 | 89 | Sub()はtime.Time同士を引き算してtime.Durationを返す関数です。 90 | */ 91 | //import "time" 92 | 93 | func time_IncDec() { 94 | 95 | t := time.Date(2001, 5, 20, 23, 59, 59, 0, time.Local) 96 | t = t.Add(time.Duration(1) * time.Second) 97 | fmt.Println(t) // => "2001-05-21 00:00:00 +0900 JST" 98 | 99 | t1 := time.Date(2000, 12, 31, 0, 0, 0, 0, time.Local) 100 | t1 = t1.Add(time.Duration(24) * time.Hour) 101 | fmt.Println(t1) // => "2001-01-01 00:00:00 +0900 JST" 102 | 103 | } 104 | 105 | //--------------------------------------------------- 106 | // 2つの時刻の差を求める 107 | //--------------------------------------------------- 108 | //import "time" 109 | 110 | func time_Duration() { 111 | day1 := time.Date(2000, 12, 31, 0, 0, 0, 0, time.Local) 112 | day2 := time.Date(2001, 1, 2, 12, 30, 0, 0, time.Local) 113 | duration := day2.Sub(day1) 114 | fmt.Println(duration) // => "60h30m0s" 115 | 116 | hours0 := int(duration.Hours()) 117 | days := hours0 / 24 118 | hours := hours0 % 24 119 | mins := int(duration.Minutes()) % 60 120 | secs := int(duration.Seconds()) % 60 121 | fmt.Printf("%d days + %d hours + %d minutes + %d seconds\n", days, hours, mins, secs) 122 | // => "2 days + 12 hours + 30 minutes + 0 seconds" 123 | } 124 | 125 | //--------------------------------------------------- 126 | // 時刻中の曜日を日本語に変換する 127 | //--------------------------------------------------- 128 | /* 129 | time.Weekday は普段はintだけどPrintln等でString()メソッドを 130 | 呼ばれると曜日の英語表記になるという型です。 131 | */ 132 | //import "time" 133 | 134 | func time_JapaneseWeekday() { 135 | wdays := [...]string{"日", "月", "火", "水", "木", "金", "土"} 136 | 137 | t := time.Now() 138 | fmt.Println(t.Weekday()) // =>"Tuesday" 139 | fmt.Println(wdays[t.Weekday()]) // =>"火" 140 | } 141 | 142 | //--------------------------------------------------- 143 | // UNIXタイムをTimeオブジェクトに変換する 144 | //--------------------------------------------------- 145 | //import "time" 146 | 147 | func time_Unix() { 148 | fmt.Println(time.Unix(1267867237, 0)) // => "2010-03-06 18:20:37 +0900 JST" 149 | fmt.Println(time.Now().Unix()) // => "1430783059" 150 | } 151 | 152 | //--------------------------------------------------- 153 | // 現在の日付を求める 154 | //--------------------------------------------------- 155 | /* Rubyのようにtime/dateの違いはありません。*/ 156 | //import "time" 157 | 158 | func time_Date() { 159 | day := time.Now() 160 | const layout = "2006-01-02" 161 | fmt.Println(day.Format(layout)) // => "2015-05-05" 162 | } 163 | 164 | //--------------------------------------------------- 165 | // 日付オブジェクトを文字列に変換する 166 | //--------------------------------------------------- 167 | //import "time" 168 | 169 | func time_DateString() { 170 | day := time.Now() 171 | const layout = "2006-01-02" 172 | fmt.Println(day.Format(layout)) // => "2015-05-05" 173 | } 174 | 175 | //--------------------------------------------------- 176 | // 日付オブジェクトを作成する 177 | ///--------------------------------------------------- 178 | //import "time" 179 | 180 | func time_MakeDate() { 181 | day := time.Date(2001, 5, 31, 0, 0, 0, 0, time.Local) 182 | fmt.Println(day) // => "2001-05-31 00:00:00 +0900 JST" 183 | } 184 | 185 | //--------------------------------------------------- 186 | // 指定の日付が存在するかどうか調べる 187 | //--------------------------------------------------- 188 | /* 189 | うーん、別途関数を書くしか無いですね。。 190 | 191 | ユリウス日の変換は[こちら](http://play.golang.org/p/ocYFWY7kpo)を参照しました。 192 | */ 193 | //import "time" 194 | 195 | func time_Exist() { 196 | jd, err := isExist(2001, 1, 31) 197 | if err != nil { 198 | fmt.Println(err) 199 | } else { 200 | fmt.Println(int(jd)) 201 | } 202 | // => "2451940" 203 | jd, err = isExist(2001, 1, 32) 204 | if err != nil { 205 | fmt.Println(err) 206 | } else { 207 | fmt.Println(int(jd)) 208 | } 209 | // => "2001-1-32 is not exist" 210 | } 211 | 212 | // 指定の日付が存在するかどうか調べる。 213 | // 存在しない日付を指定してもtime.Date()はよきに計らってくれるので、 214 | // 指定した日付と違うtime.Timeが返ってくれば指定した日付が間違ってると判定。 215 | func isExist(year, month, day int) (float64, error) { 216 | date := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local) 217 | if date.Year() == year && date.Month() == time.Month(month) && date.Day() == day { 218 | return Julian(date), nil 219 | } else { 220 | return 0, fmt.Errorf("%d-%d-%d is not exist", year, month, day) 221 | } 222 | } 223 | 224 | // ユリウス日を求める 225 | func Julian(t time.Time) float64 { 226 | // Julian date, in seconds, of the "Format" standard time. 227 | // (See http://www.onlineconversion.com/julian_date.htm) 228 | const julian = 2453738.4195 229 | // Easiest way to get the time.Time of the Unix time. 230 | // (See comments for the UnixDate in package Time.) 231 | unix := time.Unix(1136239445, 0) 232 | const oneDay = float64(86400. * time.Second) 233 | return julian + float64(t.Sub(unix))/oneDay 234 | } 235 | 236 | //--------------------------------------------------- 237 | // ユリウス日から日付オブジェクトを作成する 238 | //--------------------------------------------------- 239 | /* なんだか誤差が残りますが..。*/ 240 | //import "time" 241 | 242 | func time_FromJulian() { 243 | t := time.Date(2001, 1, 31, 0, 0, 0, 0, time.Local) 244 | jd := Julian(t) 245 | fmt.Println(jd) // => "2.451940124997685e+06" 246 | fmt.Println(FromJulian(jd)) // => "2001-01-31 00:00:00.000014592 +0900 JST" 247 | } 248 | 249 | // ユリウス日から時間に 250 | func FromJulian(jd float64) time.Time { 251 | const julian = 2453738.4195 252 | unix := time.Unix(1136239445, 0) 253 | const oneDay = float64(86400. * time.Second) 254 | return unix.Add(time.Duration((jd - julian) * oneDay)) 255 | } 256 | 257 | //--------------------------------------------------- 258 | // 何日後、何日前の日付を求める 259 | //--------------------------------------------------- 260 | /* AddDateが使えます。引数はyear,month,dayの順です。*/ 261 | //import "time" 262 | 263 | func time_IncDecDay() { 264 | t := time.Date(2001, 5, 31, 0, 0, 0, 0, time.Local) 265 | t = t.AddDate(0, 0, 1) 266 | fmt.Println(t) // => "2001-06-01 00:00:00 +0900 JST" 267 | 268 | t = time.Date(2001, 1, 1, 0, 0, 0, 0, time.Local) 269 | t = t.AddDate(0, 0, -1) 270 | fmt.Println(t) // => "2000-12-31 00:00:00 +0900 JST" 271 | } 272 | 273 | //--------------------------------------------------- 274 | // 何ヶ月後、何ヶ月前の日付を求める 275 | //--------------------------------------------------- 276 | /* 277 | rubyは 1/31 -> 2/28など月末を意識したメソッドのようですね。 278 | AddDate()で単純に1ヶ月足すと、2/31 = 3/3 のように変換されて 279 | しまいます。ので、最終日を意識した加減のメソッドAddMonthを作ります。 280 | */ 281 | //import "time" 282 | 283 | func time_IncDecMonth() { 284 | t0 := time.Date(2001, 1, 31, 0, 0, 0, 0, time.Local) 285 | t1 := t0.AddDate(0, 1, 0) 286 | t2 := AddMonth(t0, 1) 287 | fmt.Println(t1) // => "2001-03-03 00:00:00 +0900 JST" 288 | fmt.Println(t2) // => "2001-02-28 00:00:00 +0900 JST" 289 | t0 = time.Date(2001, 5, 31, 0, 0, 0, 0, time.Local) 290 | t1 = t0.AddDate(0, -1, 0) 291 | t2 = AddMonth(t0, -1) 292 | fmt.Println(t1) // => "2001-05-01 00:00:00 +0900 JST" 293 | fmt.Println(t2) // => "2001-04-30 00:00:00 +0900 JST" 294 | } 295 | 296 | // ruby風の月加算。これだとうるう秒に対応できてませんが。。 297 | func AddMonth(t time.Time, d_month int) time.Time { 298 | year := t.Year() 299 | month := t.Month() 300 | day := t.Day() 301 | newMonth := int(month) + d_month 302 | newLastDay := getLastDay(year, newMonth) 303 | var newDay int 304 | if day > newLastDay { 305 | newDay = newLastDay 306 | } else { 307 | newDay = day 308 | } 309 | 310 | return time.Date(year, time.Month(newMonth), newDay, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location()) 311 | 312 | } 313 | 314 | // その月の最終日を求める 315 | func getLastDay(year, month int) int { 316 | t := time.Date(year, time.Month(month+1), 1, 0, 0, 0, 0, time.Local) 317 | t = t.AddDate(0, 0, -1) 318 | return t.Day() 319 | } 320 | 321 | //--------------------------------------------------- 322 | // うるう年かどうか判定する 323 | //--------------------------------------------------- 324 | func time_LeapYear() { 325 | fmt.Println(isLeapYear(2000)) // => "true" 326 | fmt.Println(isLeapYear(2001)) // => "false" 327 | } 328 | 329 | // うるう年かどうか判定する 330 | func isLeapYear(year int) bool { 331 | if year%400 == 0 { // 400で割り切れたらうるう年 332 | return true 333 | } else if year%100 == 0 { // 100で割り切れたらうるう年じゃない 334 | return false 335 | } else if year%4 == 0 { // 4で割り切れたらうるう年 336 | 337 | return true 338 | } else { 339 | return false 340 | } 341 | } 342 | 343 | //--------------------------------------------------- 344 | // 日付オブジェクトの年月日・曜日を個別に扱う 345 | //--------------------------------------------------- 346 | //import "time" 347 | 348 | func time_Decompose() { 349 | t := time.Date(2001, 1, 31, 0, 0, 0, 0, time.Local) 350 | fmt.Println(t.Year()) // => "2001" 351 | fmt.Println(t.Month()) // => "January" 352 | fmt.Println(t.Day()) // => "31" 353 | fmt.Println(t.Weekday()) // => "Wednesday" 354 | } 355 | 356 | //--------------------------------------------------- 357 | // 文字列の日付を日付オブジェクトに変換する 358 | //--------------------------------------------------- 359 | /* 360 | Parseもフォーマット整形と同じように 361 | 362 | "Mon Jan 2 15:04:05 -0700 MST 2006" 363 | 364 | をひな形(layout)にして与えます 365 | */ 366 | //import "time" 367 | 368 | func time_Parse() { 369 | str := "Thu May 24 22:56:30 JST 2001" 370 | layout := "Mon Jan 2 15:04:05 MST 2006" 371 | t, _ := time.Parse(layout, str) 372 | fmt.Println(t) // => "2001-05-24 22:56:30 +0900 JST" 373 | 374 | str = "2003/04/18" 375 | layout = "2006/01/02" 376 | t, _ = time.Parse(layout, str) 377 | fmt.Println(t) // => "2003-04-18 00:00:00 +0000 UTC" 378 | } 379 | 380 | //--------------------------------------------------- 381 | // 日付と時刻 382 | //--------------------------------------------------- 383 | func Tips_time() { 384 | time_Now() // 現在の時刻を取得する 385 | time_Make() // 時刻オブジェクトを作成する 386 | time_Format() // 時刻を任意のフォーマットで扱う 387 | time_ToString() // 時刻オブジェクトを文字列に変換する 388 | time_IncDec() // 時刻に任意の時間を加減する 389 | time_Duration() // 2つの時刻の差を求める 390 | time_JapaneseWeekday() // 時刻中の曜日を日本語に変換する 391 | time_Unix() // UNIXタイムをTimeオブジェクトに変換する 392 | time_Date() // 現在の日付を求める 393 | time_DateString() // 日付オブジェクトを文字列に変換する 394 | time_MakeDate() // 日付オブジェクトを作成する 395 | time_Exist() // 指定の日付が存在するかどうか調べる 396 | time_FromJulian() // ユリウス日から日付オブジェクトを作成する 397 | time_IncDecDay() // 何日後、何日前の日付を求める 398 | time_IncDecMonth() // 何ヶ月後、何ヶ月前の日付を求める 399 | time_LeapYear() // うるう年かどうか判定する 400 | time_Decompose() // 日付オブジェクトの年月日・曜日を個別に扱う 401 | time_Parse() // 文字列の日付を日付オブジェクトに変換する 402 | 403 | } 404 | -------------------------------------------------------------------------------- /pkg/tips_string/tips_string.go: -------------------------------------------------------------------------------- 1 | /* 2 | 文字列 3 | */ 4 | 5 | package tips_string 6 | 7 | import ( 8 | "bufio" 9 | "bytes" 10 | "crypto/md5" 11 | "fmt" 12 | . "github.com/MakeNowJust/heredoc/dot" 13 | . "golang.org/x/text/encoding/japanese" 14 | "golang.org/x/text/transform" 15 | "io" 16 | "os" 17 | "os/exec" 18 | "regexp" 19 | "strconv" 20 | "strings" 21 | ) 22 | 23 | //--------------------------------------------------- 24 | // 文字列を結合する 25 | //--------------------------------------------------- 26 | func string_Concat() { 27 | a := "Hello" 28 | b := a + " World" 29 | fmt.Println(b) 30 | } 31 | 32 | //--------------------------------------------------- 33 | // 繰り返し文字列を生成する 34 | //--------------------------------------------------- 35 | // import "strings" 36 | 37 | func string_Repeat() { 38 | s := "Hey " 39 | fmt.Println(strings.Repeat(s, 3)) 40 | } 41 | 42 | //--------------------------------------------------- 43 | // 大文字・小文字に揃える 44 | //--------------------------------------------------- 45 | //import "strings" 46 | 47 | func string_UpperLower() { 48 | s := "I love GoLang" 49 | fmt.Println(strings.ToUpper(s)) 50 | fmt.Println(strings.ToLower(s)) 51 | } 52 | 53 | //--------------------------------------------------- 54 | // 大文字と小文字の入れ替え 55 | //--------------------------------------------------- 56 | //import "strings" 57 | 58 | func string_ReplaceUpperLower() { 59 | //うーん、かなりイマイチ 60 | s := "i lOVE gOLANG" 61 | sr := "" 62 | for _, x := range s { 63 | xs := string(x) 64 | u := strings.ToUpper(xs) 65 | l := strings.ToLower(xs) 66 | if u == xs { 67 | sr += l 68 | } else if l == xs { 69 | sr += u 70 | } else { 71 | sr += xs 72 | } 73 | } 74 | fmt.Println(sr) 75 | } 76 | 77 | //--------------------------------------------------- 78 | // コマンドの実行結果を文字列に 79 | //--------------------------------------------------- 80 | // import "os/exec" 81 | 82 | func string_Exec() { 83 | out, _ := exec.Command("date").Output() 84 | fmt.Println(string(out)) 85 | } 86 | 87 | //--------------------------------------------------- 88 | // 複数行の文字列を作成する 89 | //--------------------------------------------------- 90 | func string_HereDocument() { 91 | s := ` 92 | This is a test. 93 | 94 | GoLang, programming language developed at Google. 95 | ` 96 | fmt.Println(s) 97 | } 98 | 99 | //--------------------------------------------------- 100 | // ヒアドキュメントの終端文字列をインデントする 101 | //--------------------------------------------------- 102 | /* 103 | そういうパッケージがありました。 104 | */ 105 | // import . "github.com/MakeNowJust/heredoc/dot" 106 | 107 | func string_HereDocumentIndent() { 108 | s := D(` 109 | This is a test. 110 | 111 | GoLang, programming language developed at Google. 112 | `) 113 | fmt.Println(s) 114 | } 115 | 116 | //--------------------------------------------------- 117 | // 複数行のコマンドの実行結果を文字列に設定する 118 | //--------------------------------------------------- 119 | /* 120 | exec.Command()を使います。 121 | (echoはシェル組み込みコマンドのせいか実行されない。。) 122 | */ 123 | // import "os/exec" 124 | 125 | func string_ExecMultiLine() { 126 | s := D(` 127 | date 128 | echo "-----------------------------" 129 | ps 130 | `) 131 | outs := "" 132 | for _, s = range strings.Split(s, "\n") { 133 | out, _ := exec.Command(s).Output() 134 | outs += string(out) 135 | } 136 | fmt.Println(outs) 137 | } 138 | 139 | //--------------------------------------------------- 140 | // 部分文字列を取り出す 141 | //--------------------------------------------------- 142 | func string_Extract() { 143 | s := "Apple Banana Orange" 144 | fmt.Println(s[0:5]) // => Apple 145 | fmt.Println(s[6:(6 + 6)]) // => Banana 146 | fmt.Println(s[0:3]) // => App 147 | fmt.Println(s[6]) // => 66 148 | fmt.Println(s[13:19]) // => Orange 149 | } 150 | 151 | //--------------------------------------------------- 152 | // 部分文字列を置き換える 153 | //--------------------------------------------------- 154 | /* (うーんいまいち。。) */ 155 | //import "strings" 156 | 157 | func string_ReplacePart() { 158 | s := "Apple Banana Orange" 159 | ss := strings.Split(s, "") 160 | srep := strings.Split("Vine ", "") 161 | for i, _ := range srep { 162 | ss[i] = srep[i] 163 | } 164 | 165 | fmt.Println(strings.Join(ss, "")) 166 | } 167 | 168 | //--------------------------------------------------- 169 | // 文字列中の式を評価し値を展開する 170 | //--------------------------------------------------- 171 | /* intなら%dでもよいですが、型推定をよさげに行うのなら%vが使えます。*/ 172 | func string_Eval() { 173 | value := 123 174 | fmt.Printf("value is %v\n", value) 175 | } 176 | 177 | //--------------------------------------------------- 178 | // 文字列を1文字ずつ処理する 179 | //--------------------------------------------------- 180 | /* 181 | [こちら](http://knightso.hateblo.jp/entry/2014/06/24/090719)によると、 182 | string[n]だとbyte単位、rangeで回すとrune(utf-8文字)単位らしいです。 183 | */ 184 | func string_Each() { 185 | sum := 0 186 | for _, c := range "Golang" { 187 | sum = sum + int(c) 188 | } 189 | fmt.Println(sum) 190 | } 191 | 192 | //--------------------------------------------------- 193 | // 文字列の先頭と末尾の空白文字を削除する 194 | //--------------------------------------------------- 195 | /*空白ならTrimSpace, 任意の文字でやりたければTrimでやれます。*/ 196 | //import "strings" 197 | 198 | func string_Trim() { 199 | s := " Hello, Golang! " 200 | s = strings.TrimSpace(s) 201 | fmt.Println(s) 202 | } 203 | 204 | //--------------------------------------------------- 205 | // 文字列を整数に変換する (to_i) 206 | //--------------------------------------------------- 207 | //import "strconv" 208 | 209 | func string_ToI() { 210 | i := 1 211 | s := "999" 212 | si, _ := strconv.Atoi(s) 213 | i = i + si 214 | fmt.Println(i) 215 | } 216 | 217 | //--------------------------------------------------- 218 | // 文字列を浮動小数点に変換する (to_f) 219 | //--------------------------------------------------- 220 | //import "strconv" 221 | 222 | func string_ToF() { 223 | s := "10" 224 | sf, _ := strconv.ParseFloat(s, 64) //64 bit float 225 | fmt.Println(sf) 226 | } 227 | 228 | //--------------------------------------------------- 229 | // 8進文字列を整数に変換する 230 | //--------------------------------------------------- 231 | //import "strconv" 232 | 233 | func string_ParseOct() { 234 | s := "010" 235 | so, _ := strconv.ParseInt(s, 8, 64) // base 8, 64bit 236 | fmt.Println(so) 237 | } 238 | 239 | //--------------------------------------------------- 240 | // 16進文字列を整数に変換する 241 | //--------------------------------------------------- 242 | /* 243 | [こちら](http://ymotongpoo.hatenablog.com/entry/2015/05/20/143004)のご指摘どおり、 244 | baseを0にすると0xを入れてもいいそうです。 245 | */ 246 | 247 | //import "strconv" 248 | 249 | func string_ParseHex() { 250 | s := "ff" // 0xは含んではいけません。 251 | sh, _ := strconv.ParseInt(s, 16, 64) 252 | fmt.Println(sh) 253 | 254 | s = "0xff" // 0xを含んでも良い 255 | sh, _ = strconv.ParseInt(s, 0, 64) 256 | fmt.Println(sh) 257 | 258 | } 259 | 260 | //--------------------------------------------------- 261 | // ASCII文字をコード値に(コード値をASCII文字に)変換する 262 | //--------------------------------------------------- 263 | func string_AtoI() { 264 | s := "ABC" 265 | fmt.Println(s[0]) 266 | fmt.Println(string(82)) 267 | } 268 | 269 | //--------------------------------------------------- 270 | // 文字列を中央寄せ・左詰・右詰する 271 | //--------------------------------------------------- 272 | //import "strings" 273 | 274 | func string_Just() { 275 | //右詰、左詰めはformat文字列が対応しています。±で指定。 276 | s := "Go" 277 | fmt.Printf("%10s\n", s) 278 | fmt.Printf("%-10s\n", s) 279 | 280 | //センタリングはなさそうです。 281 | l := 10 282 | ls := (l - len(s)) / 2 283 | cs := strings.Repeat(" ", ls) + s + strings.Repeat(" ", l-(ls+len(s))) 284 | fmt.Println(cs) 285 | } 286 | 287 | //--------------------------------------------------- 288 | // "次"の文字列を取得する 289 | //--------------------------------------------------- 290 | func string_Succ() { 291 | fmt.Println(succ("9")) // => "10" 292 | fmt.Println(succ("a")) // => "b" 293 | fmt.Println(succ("AAA")) // => "AAB" 294 | fmt.Println(succ("A99")) // => "B00" 295 | fmt.Println(succ("A099")) // => "A100" 296 | } 297 | 298 | // 文字列を反転して返す 299 | func reverse(s string) string { 300 | ans := "" 301 | for i, _ := range s { 302 | ans += string(s[len(s)-i-1]) 303 | } 304 | return string(ans) 305 | } 306 | 307 | // "次"の文字列を取得する 308 | func succ(s string) string { 309 | r := reverse(s) 310 | ans := "" 311 | carry := 1 312 | lastLetter := string(r[0]) 313 | for i, _ := range r { 314 | lastLetter = string(r[i]) 315 | a := lastLetter 316 | if carry == 1 { 317 | if lastLetter == "z" { 318 | a = "a" 319 | carry = 1 320 | } else if lastLetter == "Z" { 321 | a = "A" 322 | carry = 1 323 | } else if lastLetter == "9" { 324 | a = "0" 325 | carry = 1 326 | } else { 327 | if r[i] == 0 { 328 | a = "1" 329 | } else { 330 | a = string(r[i] + 1) 331 | carry = 0 332 | } 333 | } 334 | } 335 | ans += a 336 | } 337 | if carry == 1 { 338 | if lastLetter == "9" { 339 | ans += "1" 340 | } else if lastLetter == "z" { 341 | ans += "a" 342 | } else if lastLetter == "Z" { 343 | ans += "A" 344 | } 345 | } 346 | return reverse(ans) 347 | } 348 | 349 | //--------------------------------------------------- 350 | // 文字列を暗号化する 351 | //--------------------------------------------------- 352 | /*とりあえずMD5あたりの例を書いておきます。*/ 353 | //import "crypto/md5" 354 | //import "io" 355 | //import "bufio" 356 | 357 | func string_Crypt() { 358 | h := md5.New() 359 | io.WriteString(h, "hogehoge") 360 | 361 | fmt.Print("input password >") 362 | scanner := bufio.NewScanner(os.Stdin) 363 | scanner.Scan() 364 | 365 | h2 := md5.New() 366 | io.WriteString(h2, scanner.Text()) 367 | 368 | if h2.Sum(nil)[0] == h.Sum(nil)[0] { 369 | fmt.Println("right") 370 | } else { 371 | fmt.Println("wrong") 372 | } 373 | 374 | } 375 | 376 | //--------------------------------------------------- 377 | // 文字列中で指定したパターンにマッチする部分を置換する 378 | //--------------------------------------------------- 379 | //import "strings" 380 | 381 | func string_Replace() { 382 | s := "Apple Banana Apple Orange" 383 | s = strings.Replace(s, "Apple", "Pine", 1) // 最後の引数は回数 384 | fmt.Println(s) 385 | s = strings.Replace(s, "Apple", "Pine", -1) // <0で無制限 386 | fmt.Println(s) 387 | } 388 | 389 | //--------------------------------------------------- 390 | // 文字列中に含まれている任意文字列の位置を求める 391 | //--------------------------------------------------- 392 | //import "strings" 393 | 394 | func string_Find() { 395 | s := "Apple Banana Apple Orange" 396 | fmt.Println(strings.Index(s, "Apple")) // => 0 397 | fmt.Println(strings.Index(s, "Banana")) // => 6 398 | // 途中から検索する方法は無いのでスライスで渡す 399 | fmt.Println(strings.Index(s[6:], "Apple") + 6) // => 13 400 | // 後方検索はLastIndex() 401 | fmt.Println(strings.LastIndex(s, "Apple")) // => 13 402 | fmt.Println(strings.Index(s[:(len(s)-6)], "Apple")) // => 0 403 | } 404 | 405 | //--------------------------------------------------- 406 | // 文字列の末端の改行を削除する 407 | //--------------------------------------------------- 408 | //import "strings" 409 | 410 | func string_Chomp() { 411 | s := "Hello, Golang!\n" 412 | s = strings.TrimRight(s, "\n") 413 | fmt.Println(s) 414 | } 415 | 416 | //--------------------------------------------------- 417 | // カンマ区切りの文字列を扱う 418 | //--------------------------------------------------- 419 | //import "strings" 420 | 421 | func string_Split() { 422 | 423 | s := "001,ASHITANI Tatsuji,Yokohama" 424 | slice := strings.Split(s, ",") 425 | for _, x := range slice { 426 | fmt.Println(x) 427 | } 428 | } 429 | 430 | //--------------------------------------------------- 431 | // 任意のパターンにマッチするものを全て抜き出す 432 | //--------------------------------------------------- 433 | // import "regexp" 434 | 435 | func string_FindAll() { 436 | s := "hoge:045-111-2222 boke:045-222-2222" 437 | re, _ := regexp.Compile("(\\S+):([\\d\\-]+)") 438 | ans := re.FindAllStringSubmatch(s, -1) // [マッチした全体,1個目のカッコ,2個目のカッコ,..]の配列 439 | fmt.Println(ans) 440 | } 441 | 442 | //--------------------------------------------------- 443 | // 漢字コードを変換する 444 | //--------------------------------------------------- 445 | /* 446 | 下記はEUCの例です。 447 | 指定するコーディングは、EUCJP,ISO2022JP,ShiftJISのどれかです。 448 | 449 | [こちら](http://ymotongpoo.hatenablog.com/entry/2015/05/20/143004)でご指摘いただいた点を 450 | 修正しました。'EUCJP'は'japanese.EUCJP'と呼びます。 451 | */ 452 | //import "golang.org/x/text/encoding/japanese" 453 | //import "golang.org/x/text/transform" 454 | //import "strings" 455 | //import "io" 456 | //import "os" 457 | //import "bytes" 458 | 459 | func string_Kconv() { 460 | KconvFwrite() // ファイル書き込み 461 | KconvFread() // ファイル読み出し 462 | KconvToBuffer() // バッファに書き込み 463 | KconvFromBuffer() // バッファから読み出し 464 | } 465 | 466 | // ファイル書き込み 467 | func KconvFwrite() { 468 | s := "漢字です" // UTF8 469 | f, _ := os.Create("EUC.txt") 470 | r := strings.NewReader(s) 471 | w := transform.NewWriter(f, japanese.EUCJP.NewEncoder()) // Encoder->f 472 | io.Copy(w, r) // r -> w(->Encoder->f) 473 | f.Close() 474 | } 475 | 476 | // ファイル読み出し 477 | func KconvFread() { 478 | f, _ := os.Open("EUC.txt") 479 | b := new(bytes.Buffer) 480 | r := transform.NewReader(f, japanese.EUCJP.NewDecoder()) // f -> Decoder 481 | io.Copy(b, r) // (f->Decoder)->b 482 | fmt.Println(b.String()) 483 | f.Close() 484 | } 485 | 486 | // バッファに書き込み 487 | func KconvToBuffer() { 488 | s := "漢字です" // UTF8 489 | b := new(bytes.Buffer) 490 | r := strings.NewReader(s) 491 | w := transform.NewWriter(b, japanese.EUCJP.NewEncoder()) // Encoder->f 492 | io.Copy(w, r) // r -> w(->Encoder->f) 493 | 494 | st := b.String() 495 | for i := 0; i < len(st); i++ { 496 | fmt.Println(st[i]) 497 | } 498 | fmt.Println(b.String()) 499 | 500 | } 501 | 502 | // バッファから読み出し 503 | func KconvFromBuffer() { 504 | str_bytes := []byte{180, 193, 187, 250, 164, 199, 164, 185} 505 | s := bytes.NewBuffer(str_bytes).String() // "漢字です" in EUC 506 | 507 | sr := strings.NewReader(s) 508 | b := new(bytes.Buffer) 509 | r := transform.NewReader(sr, japanese.EUCJP.NewDecoder()) // sr -> Decoder 510 | io.Copy(b, r) // (sr->Decoder)->b 511 | fmt.Println(b.String()) 512 | } 513 | 514 | //--------------------------------------------------- 515 | // マルチバイト文字の数を数える 516 | //--------------------------------------------------- 517 | /* 518 | [こちら](http://qiita.com/reiki4040/items/b82bf5056ee747dcf713)が詳しいです。 519 | len()だとbyteカウント、[]runeに変換するとutf-8カウント。 520 | */ 521 | func string_Count() { 522 | s := "日本語" 523 | fmt.Println(len(s)) // => 9 524 | fmt.Println(len([]rune(s))) // => 3 525 | } 526 | 527 | //--------------------------------------------------- 528 | // マルチバイト文字列の最後の1文字を削除する 529 | //--------------------------------------------------- 530 | func string_ChopRune() { 531 | s := "日本語" 532 | sc := []rune(s) 533 | fmt.Println(string(sc[:(len(sc) - 1)])) // => "日本" 534 | } 535 | 536 | //--------------------------------------------------- 537 | // 文字列 538 | //--------------------------------------------------- 539 | func Tips_string() { 540 | string_Concat() // 文字列を結合する 541 | string_Repeat() // 繰り返し文字列を生成する 542 | string_UpperLower() // 大文字・小文字に揃える 543 | string_Exec() // コマンドの実行結果を文字列に 544 | string_HereDocument() // 複数行の文字列を作成する 545 | string_HereDocumentIndent() // ヒアドキュメントの終端文字列をインデントする 546 | string_ExecMultiLine() // 複数行のコマンドの実行結果を文字列に設定する 547 | string_Extract() // 部分文字列を取り出す 548 | string_ReplacePart() // 部分文字列を置き換える 549 | string_Eval() // 文字列中の式を評価し値を展開する 550 | string_Each() // 文字列を1文字ずつ処理する 551 | string_Trim() // 文字列の先頭と末尾の空白文字を削除する 552 | string_ToI() // 文字列を整数に変換する (to_i) 553 | string_ToF() // 文字列を浮動小数点に変換する (to_f) 554 | string_ParseOct() // 8進文字列を整数に変換する 555 | string_ParseHex() // 16進文字列を整数に変換する 556 | string_AtoI() // ASCII文字をコード値に(コード値をASCII文字に)変換する 557 | string_Just() // 文字列を中央寄せ・左詰・右詰する 558 | string_Succ() // "次"の文字列を取得する 559 | string_Crypt() // 文字列を暗号化する 560 | string_Replace() // 文字列中で指定したパターンにマッチする部分を置換する 561 | string_Find() // 文字列中に含まれている任意文字列の位置を求める 562 | string_Chomp() // 文字列の末端の改行を削除する 563 | string_Split() // カンマ区切りの文字列を扱う 564 | string_FindAll() // 任意のパターンにマッチするものを全て抜き出す 565 | string_Kconv() // 漢字コードを変換する 566 | string_Count() // マルチバイト文字の数を数える 567 | string_ChopRune() // マルチバイト文字列の最後の1文字を削除する 568 | 569 | } 570 | -------------------------------------------------------------------------------- /pkg/tips_file/tips_file.go: -------------------------------------------------------------------------------- 1 | /* 2 | ファイル 3 | */ 4 | 5 | package tips_file 6 | 7 | import ( 8 | "bufio" 9 | "fmt" 10 | "io/ioutil" 11 | "os" 12 | "path/filepath" 13 | "regexp" 14 | "sort" 15 | "strconv" 16 | "strings" 17 | "syscall" 18 | "time" 19 | ) 20 | 21 | //--------------------------------------------------- 22 | // ファイルをオープンする 23 | //--------------------------------------------------- 24 | /* 25 | 読み出しには`os.Open()`書き込みには`os.Create()`を使います。 26 | 27 | テキストの読み書きはいろいろ方法があると思いますが、ここでは 28 | 読み出しに`bufio.NewScanner()`を、書き込みに`bufio.NewWriter()`を使います。 29 | 30 | 下記のようにWriteFile/ReadFileを使うと、一行で読み書きができます。ただし 31 | 引数はstringではなくbyte[]です。 32 | ``` 33 | // Write 34 | ioutil.WriteFile(filename, []byte(s), os.ModePerm) 35 | 36 | // Read 37 | b, err := ioutil.ReadFile(filename) 38 | s=string(b) 39 | ``` 40 | 41 | */ 42 | // import "os" 43 | // import "bufio" 44 | 45 | func file_Open() { 46 | // 書き込み 47 | fpw, err := os.Create("test.txt") 48 | if err != nil { 49 | panic(err) 50 | } 51 | 52 | w := bufio.NewWriter(fpw) 53 | fmt.Fprint(w, "Hello, golang!") 54 | w.Flush() 55 | fpw.Close() 56 | 57 | // 読み出し 58 | fp, err := os.Open("test.txt") 59 | if err != nil { 60 | panic(err) 61 | } 62 | scanner := bufio.NewScanner(fp) 63 | for scanner.Scan() { 64 | fmt.Println(scanner.Text()) 65 | } 66 | fp.Close() 67 | } 68 | 69 | //--------------------------------------------------- 70 | // テキストファイルをオープンして内容を出力する 71 | //--------------------------------------------------- 72 | /* 73 | [ファイルをオープンする](#file_Open)と同じ内容ですが。 74 | */ 75 | // import "os" 76 | // import "bufio" 77 | 78 | func file_Read() { 79 | fp, err := os.Open("test.txt") 80 | if err != nil { 81 | panic(err) 82 | } 83 | scanner := bufio.NewScanner(fp) 84 | for scanner.Scan() { 85 | fmt.Println(scanner.Text()) 86 | } 87 | fp.Close() 88 | } 89 | 90 | //--------------------------------------------------- 91 | // 読み込む長さを指定する 92 | //--------------------------------------------------- 93 | /* 94 | []byteバッファを作ってRead()に渡すと、バッファの長さ分だけ 95 | 読み込んでくれます。 96 | */ 97 | // import "os" 98 | 99 | func file_ReadLength() { 100 | fp, err := os.Open("test.txt") 101 | if err != nil { 102 | panic(err) 103 | } 104 | 105 | data := make([]byte, 10) 106 | count, err := fp.Read(data) 107 | 108 | if err != nil { 109 | panic(err) 110 | } 111 | fmt.Printf("Read %d bytes: %s\n", count, data) 112 | } 113 | 114 | //--------------------------------------------------- 115 | // ファイルの内容を一度に読み込む 116 | //--------------------------------------------------- 117 | /* 118 | io/ioutilのioutil.ReadFile()を使います。 119 | */ 120 | // import "io/ioutil" 121 | 122 | func file_ReadAll() { 123 | data, err := ioutil.ReadFile("test.txt") 124 | if err != nil { 125 | panic(err) 126 | } 127 | fmt.Println(string(data)) 128 | } 129 | 130 | //--------------------------------------------------- 131 | // 1行ずつ読み込みを行う 132 | //--------------------------------------------------- 133 | /* 134 | bufioのScannerをつかってみます。この例では、foo.csvから行数と総エントリ数をカウントします。 135 | */ 136 | // import "bufio" 137 | // import "os" 138 | // import "strings" 139 | 140 | func file_ReadEachLine() { 141 | data, err := readAll("foo.csv") 142 | if err != nil { 143 | panic(err) 144 | } 145 | fmt.Println(string(data)) 146 | } 147 | 148 | func readAll(filename string) (string, error) { 149 | fp, err := os.Open(filename) 150 | if err != nil { 151 | return "", fmt.Errorf(filename + " can't be opened") 152 | } 153 | 154 | ans := "" 155 | lines := 0 156 | entries := 0 157 | 158 | scanner := bufio.NewScanner(fp) 159 | for scanner.Scan() { 160 | entry := scanner.Text() 161 | lines += 1 162 | slice := strings.Split(entry, ",") 163 | entries += len(slice) 164 | } 165 | 166 | fp.Close() 167 | fmt.Printf("Read %d lines, %d entries\n", lines, entries) 168 | return string(ans), nil 169 | } 170 | 171 | //--------------------------------------------------- 172 | // テキストファイルの特定の行を読み込む 173 | //--------------------------------------------------- 174 | /* 175 | rubyのreadlinesのように、配列に読み込むような標準関数はありません。 176 | 改行でSplitすれば代替になりますが、でかいファイルの場合は気をつけないとですね。 177 | */ 178 | // import "ioutil" 179 | // import "strings" 180 | 181 | func file_ReadSpecificLine() { 182 | ans, err := readLines("foo.csv") 183 | if err != nil { 184 | panic(err) 185 | } 186 | fmt.Println(ans[1]) 187 | } 188 | 189 | func readLines(filename string) ([]string, error) { 190 | ans := make([]string, 10) 191 | data, err := ioutil.ReadFile(filename) 192 | if err != nil { 193 | return ans, fmt.Errorf(filename + " can't be opened") 194 | } 195 | ans = strings.Split(string(data), "\n") 196 | 197 | return ans, err 198 | } 199 | 200 | //--------------------------------------------------- 201 | // 一時ファイルを作成する 202 | //--------------------------------------------------- 203 | /* 204 | ioutil.TempFile(dir,prefix string)を使います。dirは一時ファイルを 205 | 作成するフォルダです。""を指定すると 206 | osごとのデフォルトのディレクトリが使われるようです。prefixに指定した文字が 207 | ファイル名に入ります。 208 | 209 | 下記の例は、test.txtの内容を、TempFileを利用して大文字に変換します。 210 | */ 211 | // import "bufio" 212 | // import "ioutil" 213 | // import "os" 214 | 215 | func file_TempFile() { 216 | 217 | f, err := os.Open("test.txt") 218 | if err != nil { 219 | panic(err) 220 | } 221 | 222 | fw, err := ioutil.TempFile(".", "temp") 223 | if err != nil { 224 | panic(err) 225 | } 226 | 227 | scanner := bufio.NewScanner(f) 228 | for scanner.Scan() { 229 | entry := scanner.Text() 230 | fw.Write([]byte(strings.ToUpper(entry))) 231 | } 232 | 233 | fw.Close() 234 | f.Close() 235 | os.Rename(fw.Name(), f.Name()) 236 | 237 | } 238 | 239 | //--------------------------------------------------- 240 | // 固定長レコードを読む 241 | //--------------------------------------------------- 242 | /* 243 | 以下の様な固定長レコードを読みます。 244 | ``` 245 | ■レコード形式 246 | 従業員番号 6桁|氏名 utf5文字|部課コード 4桁|入社年度 4桁 247 | 248 | ■レコード例 249 | 100001鈴木一郎太12342001 250 | 251 | 従業員番号: 100001 252 | 氏名: 鈴木一郎太 253 | 部課コード: 1234 254 | 入社年度: 2001 255 | ``` 256 | 257 | record という構造体を作り、その配列recordsに対して、 258 | レコード追加・表示用のインターフェイス(Insert,List)と、 259 | ソート用のインターフェイス(Len,Less,Swap)を準備。 260 | 261 | */ 262 | // import "bufio" 263 | // import "sort" 264 | // import "strconv" 265 | // import "os" 266 | 267 | func file_FormattedText() { 268 | var rs records 269 | 270 | f, err := os.Open("fmtTxt.txt") 271 | if err != nil { 272 | panic(err) 273 | } 274 | 275 | scanner := bufio.NewScanner(f) 276 | 277 | for scanner.Scan() { 278 | entry := scanner.Text() 279 | rs.InsertFromString(entry) 280 | } 281 | 282 | sort.Sort(rs) 283 | rs.List() 284 | } 285 | 286 | type record struct { 287 | empno int 288 | name string 289 | deptno int 290 | year int 291 | } 292 | 293 | type records []record 294 | 295 | func (rs *records) InsertFromString(s string) { 296 | var newRecord record 297 | 298 | r := []rune(s) 299 | 300 | newRecord.empno, _ = strconv.Atoi(string(r[0:6])) 301 | newRecord.name = string(r[6:11]) 302 | newRecord.deptno, _ = strconv.Atoi(string(r[11:15])) 303 | newRecord.year, _ = strconv.Atoi(string(r[15:19])) 304 | *rs = append(*rs, newRecord) 305 | } 306 | 307 | func (r records) List() { 308 | for _, x := range r { 309 | fmt.Printf("従業員番号:\t%d\n", x.empno) 310 | fmt.Printf("氏名:\t\t%s\n", x.name) 311 | fmt.Printf("部課コード:\t%d\n", x.deptno) 312 | fmt.Printf("入社年度:\t%d\n", x.year) 313 | fmt.Println(strings.Repeat("-", 20)) 314 | } 315 | } 316 | 317 | func (r records) Len() int { 318 | return len(r) 319 | } 320 | 321 | func (r records) Swap(i, j int) { 322 | r[i], r[j] = r[j], r[i] 323 | } 324 | 325 | func (r records) Less(i, j int) bool { 326 | return r[i].year < r[j].year 327 | } 328 | 329 | //--------------------------------------------------- 330 | // ファイルをコピーする 331 | //--------------------------------------------------- 332 | /* 333 | os.Link()が簡単でしょう。 334 | */ 335 | // import "os" 336 | 337 | func file_CopyFile() { 338 | src := "test.txt" 339 | dest := "test.bak" 340 | _ = os.Link(src, dest) 341 | } 342 | 343 | //--------------------------------------------------- 344 | // フィルタ系のコマンドを作成する 345 | //--------------------------------------------------- 346 | /* 347 | 標準入力を受け取りたいときはos.Stdinを使います。 348 | rubyのように、ファイル名指定されたら勝手に標準入力扱いという器用なことは 349 | できないので、os.Argsでとれるコマンドライン引数リストを走査します。 350 | 351 | ``` 352 | echo hoge | go run ./main.go 353 | go run ./main.go test.txt test.bak 354 | ``` 355 | のどちらでも機能します。 356 | 357 | C言語と違って、os.Argsがどこでも機能する(mainの引数を変更する必要がない)のは 358 | 一瞬気持ち悪いですが、スッキリ書けますね。 359 | 360 | */ 361 | // import "bufio" 362 | // import "os" 363 | 364 | func file_Filter() { 365 | 366 | l := len(os.Args) 367 | if l == 1 { // 引数なしの場合 368 | scanner := bufio.NewScanner(os.Stdin) 369 | for scanner.Scan() { 370 | t := scanner.Text() 371 | if t != "" { 372 | fmt.Println(t) 373 | } else { 374 | break 375 | } 376 | } 377 | } else { // ファイル名渡しの場合 378 | for _, x := range os.Args[1:l] { 379 | f, err := os.Open(x) 380 | if err != nil { 381 | panic(err) 382 | } 383 | scanner := bufio.NewScanner(f) 384 | for scanner.Scan() { 385 | fmt.Println(scanner.Text()) 386 | } 387 | } 388 | } 389 | } 390 | 391 | //--------------------------------------------------- 392 | // ファイルタイプを取得する 393 | //--------------------------------------------------- 394 | /* 395 | [こちら](http://qiita.com/shinofara/items/e5e78e6864a60dc851a6)を参考に。 396 | os.Stat()でos.FileInfoが返ります。 397 | 398 | 存在有無は、os.Stat()のエラーをos.IsExist()に渡すと確認できます。 399 | ちょっとくどいですね。 400 | */ 401 | // import "os" 402 | 403 | func file_FileType() { 404 | fmt.Println(isDir("/etc/passwd")) // => false 405 | fmt.Println(isDir("/etc")) // => true 406 | 407 | fmt.Println(isExist("/etc/passwd")) // => true 408 | fmt.Println(isExist("/etc/password")) // => false 409 | } 410 | 411 | func isDir(filename string) bool { 412 | fInfo, _ := os.Stat(filename) 413 | return fInfo.IsDir() 414 | } 415 | 416 | func isExist(filename string) bool { 417 | _, err := os.Stat(filename) 418 | if err == nil { 419 | return true 420 | } else { 421 | return os.IsExist(err) 422 | } 423 | } 424 | 425 | //--------------------------------------------------- 426 | // ファイルの詳細情報を取得する 427 | //--------------------------------------------------- 428 | /* 429 | むかしはFileStatでi-node番号とかもろもろ取得できたようですが、 430 | 少なくともGo1.4ではsyscallにいます。Atimespec->AtimになったのはGo1.5から? 431 | */ 432 | // import "syscall" 433 | 434 | func file_Stat() { 435 | var s syscall.Stat_t 436 | syscall.Stat("/etc/passwd", &s) 437 | fmt.Println(s.Dev) 438 | fmt.Println(s.Ino) 439 | fmt.Println(s.Mode) 440 | fmt.Println(s.Nlink) 441 | fmt.Println(s.Uid) 442 | fmt.Println(s.Gid) 443 | fmt.Println(s.Size) 444 | fmt.Println(s.Blocks) 445 | // fmt.Println(s.Atim.Unix()) // Go1.4ではエラー 446 | // fmt.Println(s.Mtim.Unix()) // Go1.4ではエラー 447 | fmt.Println(s.Atimespec.Unix()) 448 | fmt.Println(s.Mtimespec.Unix()) 449 | } 450 | 451 | //--------------------------------------------------- 452 | // ファイルモードを変更する 453 | //--------------------------------------------------- 454 | /* 455 | os.Chmod()を使います。FileMode構造体が返るのですが、String()メソッドが定義されているので、 456 | Printlnすると"-rw-rw-rw-"のような表示が出ます。便利なのか?と思いましたが、 457 | 8進数を誤解しやすいからかしら。 458 | */ 459 | // import "os" 460 | 461 | func file_ChMod() { 462 | filename := "test.txt" 463 | 464 | s, _ := os.Stat(filename) 465 | fmt.Println(s.Mode()) // -> "-rw-------" 466 | 467 | os.Chmod(filename, 0666) 468 | 469 | s, _ = os.Stat(filename) 470 | fmt.Println(s.Mode()) // -> "-rw-rw-rw-" 471 | } 472 | 473 | //--------------------------------------------------- 474 | // ファイルの所有者とグループを変更する 475 | //--------------------------------------------------- 476 | /* 477 | os.Chown()があります。もちろんchwonできる権限がないとダメですが。 478 | 479 | ちなみにOSXでユーザIDを調べるのは、 480 | ``` 481 | id 482 | dscl . -read /users/$username uid 483 | ``` 484 | などの方法があります。 485 | */ 486 | //import "os" 487 | 488 | func file_ChOwn() { 489 | err := os.Chown("test.txt", 502, 20) //uid=502,gid=20 490 | if err != nil { 491 | fmt.Println("chown not permitted") 492 | } 493 | } 494 | 495 | //--------------------------------------------------- 496 | // ファイルの最終アクセス時刻と最終更新日時を変更する 497 | //--------------------------------------------------- 498 | /* 499 | 下記の例は、test.txtの 500 | 最終アクセス日を2001-5-22 23:59:59(JST)、 501 | 最終更新日を2001-5-1 00:00:00(JST)に変更するものです。 502 | */ 503 | // import "syscall" 504 | // import "time" 505 | 506 | func file_ChangeTime() { 507 | 508 | // 変更 509 | atime := time.Date(2001, 5, 22, 23, 59, 59, 0, time.Local) 510 | mtime := time.Date(2001, 5, 1, 00, 00, 00, 0, time.Local) 511 | os.Chtimes("test.txt", atime, mtime) 512 | 513 | // 確認 514 | var s syscall.Stat_t 515 | syscall.Stat("test.txt", &s) 516 | sec, nsec := s.Atimespec.Unix() // Go1.5以降ではAtimespec -> Atim 517 | fmt.Println(time.Unix(sec, nsec)) // => "2001-05-22 23:59:59 +0900 JST" 518 | sec, nsec = s.Mtimespec.Unix() // Go1.5以降ではAtimespec -> Atim 519 | fmt.Println(time.Unix(sec, nsec)) // => "2001-05-01 00:00:00 +0900 JST" 520 | 521 | } 522 | 523 | //--------------------------------------------------- 524 | // 相対パスから絶対パスを求める 525 | //--------------------------------------------------- 526 | /* 527 | カレントを基準に相対パスを絶対パスに変換するにはpath/filepathのAbs()を使います。 528 | 529 | 指定したベースパスを基準に相対パスを絶対パスに変換するにはJoin()を使います。 530 | 531 | 絶対パスを、ベースパスを基準に相対パスに変換するにはRel()を使います。 532 | */ 533 | // import "path/filepath" 534 | 535 | func file_AbsPath() { 536 | apath, _ := filepath.Abs("./test.txt") 537 | fmt.Println(apath) 538 | 539 | apath = filepath.Join("/etc", "passwd") 540 | fmt.Println(apath) // => "/etc/passwd" 541 | 542 | rpath, _ := filepath.Rel("/etc", "/etc/passwd") 543 | fmt.Println(rpath) // -> "passwd" 544 | } 545 | 546 | //--------------------------------------------------- 547 | // ファイルパスからディレクトリパスを抜き出す 548 | //--------------------------------------------------- 549 | /* 550 | path/filepath のDir()を使います。 551 | Windowsのパスはうまく展開されませんけど、OSXで実行したからかしら。 552 | */ 553 | // import "path/filepath" 554 | 555 | func file_Dir() { 556 | d := filepath.Dir("/hoge/piyo") 557 | fmt.Println(d) // =>"/hoge" 558 | 559 | d = filepath.Dir("/hoge/piyo/") 560 | fmt.Println(d) // =>"/hoge/piyo" 561 | d = filepath.Dir("c:\\hoge\\piyo") 562 | fmt.Println(d) // =>"." ?? 563 | } 564 | 565 | //--------------------------------------------------- 566 | // ファイルパスからファイル名を抜き出す 567 | //--------------------------------------------------- 568 | /* 569 | path/filepath のBase()でファイル名を分離できます。 570 | 拡張子を取り出すのはExt()ですが、拡張子を取り除いたbasenameを 571 | 取る方法は簡単にはなさそうですので、正規表現で拡張子を取り除いてからBase()を実行しました。 572 | */ 573 | // import "path/filepath" 574 | // import "regexp" 575 | 576 | func file_Basename() { 577 | b := filepath.Base("/hoge/piyo") 578 | fmt.Println(b) // => "piyo" 579 | 580 | e := filepath.Ext("/hoge/piyo.c") 581 | fmt.Println(e) // => ".c" 582 | 583 | rep := regexp.MustCompile(`.c$`) 584 | e = filepath.Base(rep.ReplaceAllString("/hoge/piyo.c", "")) 585 | fmt.Println(e) // => "piyo" 586 | } 587 | 588 | //--------------------------------------------------- 589 | // パス名とファイル名を一度に抜き出す 590 | //--------------------------------------------------- 591 | /* 592 | path/filepath のSplit()でディレクトリ名とファイル名を分離できます。 593 | */ 594 | // import "path/filepath" 595 | 596 | func file_Split() { 597 | d, f := filepath.Split("/hoge/piyo") 598 | fmt.Println(d) // => "/hoge/" 599 | fmt.Println(f) // => "piyo" 600 | } 601 | 602 | //--------------------------------------------------- 603 | // 拡張子を調べる 604 | //--------------------------------------------------- 605 | /* 606 | path/filepath のExt()で拡張子を取り出せます。 607 | */ 608 | // import "path/filepath" 609 | 610 | func file_Ext() { 611 | e := filepath.Ext("/hoge/piyo.c") 612 | fmt.Println(e) // => ".c" 613 | } 614 | 615 | //--------------------------------------------------- 616 | // ファイル 617 | //--------------------------------------------------- 618 | func Tips_file() { 619 | file_Open() // ファイルをオープンする 620 | file_Read() // テキストファイルをオープンして内容を出力する 621 | file_ReadLength() // 読み込む長さを指定する 622 | file_ReadAll() // ファイルの内容を一度に読み込む 623 | file_ReadEachLine() // 1行ずつ読み込みを行う 624 | file_ReadSpecificLine() // テキストファイルの特定の行を読み込む 625 | file_TempFile() // 一時ファイルを作成する 626 | file_FormattedText() // 固定長レコードを読む 627 | file_CopyFile() // ファイルをコピーする 628 | file_Filter() // フィルタ系のコマンドを作成する 629 | file_FileType() // ファイルタイプを取得する 630 | file_Stat() // ファイルの詳細情報を取得する 631 | file_ChMod() // ファイルモードを変更する 632 | file_ChOwn() // ファイルの所有者とグループを変更する 633 | file_ChangeTime() // ファイルの最終アクセス時刻と最終更新日時を変更する 634 | file_AbsPath() // 相対パスから絶対パスを求める 635 | file_Dir() // ファイルパスからディレクトリパスを抜き出す 636 | file_Basename() // ファイルパスからファイル名を抜き出す 637 | file_Split() // パス名とファイル名を一度に抜き出す 638 | file_Ext() // 拡張子を調べる 639 | } 640 | -------------------------------------------------------------------------------- /pkg/tips_slice/tips_slice.go: -------------------------------------------------------------------------------- 1 | /* 2 | 配列 3 | */ 4 | 5 | package tips_slice 6 | 7 | import ( 8 | "fmt" 9 | set "github.com/deckarep/golang-set" 10 | matrix "github.com/skelterjohn/go.matrix" 11 | "math/rand" 12 | "sort" 13 | "strings" 14 | "time" 15 | ) 16 | 17 | //--------------------------------------------------- 18 | //プログラムで配列を定義する 19 | //--------------------------------------------------- 20 | /* 21 | 配列は固定長、スライスは可変長の配列のようなもの、です。 22 | 個人的には、特に理由が無い限りスライスを使えばいいんじゃないかと思っています。 23 | 初期化は型をTとすると 24 | ``` 25 | a:=[]T{} 26 | a:=make([]T,len) 27 | ``` 28 | などで行います。 29 | 30 | スライスの取り扱いはGolang Wikiの[SliceTricks](https://github.com/golang/go/wiki/SliceTricks)に詳しいです。 31 | 32 | スライスの中身にいろんな型を混在させたい場合はinterface{}型で初期化します。 33 | ただし要素を取り出す際にキャストが必要です。interface型のキャストは、キャスト先の型をTとすると、 34 | ``` 35 | v,ok:=x.(T) 36 | ```と書きます。fmt.Println()などはStringへのキャストを自前で行うので注意。 37 | 38 | スライスのネストも可能ですがこれまた同じようにキャストして取り出す必要がありなかなか面倒です。 39 | 40 | */ 41 | func slice_Define() { 42 | fruits := []string{"apple", "orange", "lemon"} 43 | fmt.Println(fruits) // => "[apple orange lemon]" 44 | 45 | scores := []int{55, 49, 100, 150, 0} 46 | fmt.Println(scores) // => "[55 49 100 150 0]" 47 | 48 | tmp := []interface{}{"apple", 10, 2.5} 49 | fmt.Println(tmp) // => "[apple 10 2.5]" 50 | 51 | fruites2 := []interface{}{ 52 | 3, 53 | []interface{}{"apple", 250}, 54 | []interface{}{"orange", 400}, 55 | []interface{}{"lemon", 300}, 56 | } 57 | fmt.Println(fruites2[0].(int)) 58 | f, _ := fruites2[1].([]interface{}) 59 | fmt.Println(f[1]) // => "250" 60 | 61 | f, _ = fruites2[3].([]interface{}) 62 | fmt.Println(f[0]) // => "lemon" 63 | 64 | } 65 | 66 | //--------------------------------------------------- 67 | //m x n 行列の形で配列の配列を初期化する 68 | //--------------------------------------------------- 69 | /* 70 | スライスのスライスを作ってせっせと要素を詰めてもよいですが、 71 | 行列演算に特化したMatrixパッケージをつかってもよいでしょう。ここでは 72 | [go.matrix](https://godoc.org/github.com/skelterjohn/go.matrix) 73 | をつかってみます。Zeros, Ones, ParseMatlabなど、Matlab経験者には嬉しい 74 | 関数がそろってます。 75 | */ 76 | //import matrix "github.com/skelterjohn/go.matrix" 77 | 78 | func slice_SliceOfSlice() { 79 | 80 | // Slice of Slice 81 | dary := make([][]int, 4) 82 | for i := range dary { 83 | dary[i] = make([]int, 3) 84 | } 85 | dary[0][1] = 7 86 | fmt.Println(dary) // => "[[0 7 0] [0 0 0] [0 0 0] [0 0 0]]" 87 | 88 | // Matrix 89 | dmat := matrix.Zeros(4, 3) 90 | dmat.Set(0, 1, 7) 91 | fmt.Println(dmat) 92 | // =>{0, 7, 0, 93 | // 0, 0, 0, 94 | // 0, 0, 0, 95 | // 0, 0, 0} 96 | } 97 | 98 | //--------------------------------------------------- 99 | //配列要素をカンマ区切りで出力する 100 | //--------------------------------------------------- 101 | // import "strings" 102 | 103 | func slice_Join() { 104 | // stringならJoin一発 105 | fruits := []string{"apple", "orange", "lemon"} 106 | fmt.Println(strings.Join(fruits, ",")) // => "apple,orange,lemon" 107 | fmt.Println(strings.Join(fruits, "#")) // => "apple#orange#lemon" 108 | 109 | //Joinはstringしかできない。。map,reduceみたいなのもないし、しょうがないか。 110 | numbers := []int{55, 49, 100, 100, 0} 111 | str := "" 112 | for _, v := range numbers { 113 | str += fmt.Sprintf("%d,", v) 114 | } 115 | str = strings.TrimRight(str, ",") //右端の","を取り除く 116 | fmt.Println(str) // => "55,49,100,100,0" 117 | 118 | //チートなやり方としては、Sprintfの整形を利用する。。 119 | str = fmt.Sprintf("%v", numbers) 120 | str = strings.Trim(str, "[]") 121 | str = strings.Replace(str, " ", ",", -1) 122 | fmt.Println(str) // => "55,49,100,100,0" 123 | 124 | //うーんこれもかなり辛い。。 125 | fruits2 := []interface{}{ 126 | 3, 127 | []interface{}{"apple", 250}, 128 | []interface{}{"orange", 400}, 129 | } 130 | str = "" 131 | for _, v := range fruits2 { 132 | w, ok := v.([]interface{}) 133 | if ok == false { 134 | str += fmt.Sprintf("%v,", v) 135 | } else { 136 | for _, x := range w { 137 | str += fmt.Sprintf("%v,", x) 138 | } 139 | } 140 | } 141 | str = strings.TrimRight(str, ",") //右端の","を取り除く 142 | fmt.Println(str) // => "3,apple,250,orange,400" 143 | 144 | } 145 | 146 | //--------------------------------------------------- 147 | //配列の要素数を取得する 148 | //--------------------------------------------------- 149 | func slice_Count() { 150 | fruits := []string{"apple", "orange", "lemon"} 151 | fmt.Println(len(fruits)) // => "3" 152 | 153 | num := []int{55, 49, 100, 100, 0} 154 | fmt.Println(len(num)) // => "5" 155 | 156 | fruits2 := []interface{}{ 157 | 3, 158 | []interface{}{"apple", 250}, 159 | []interface{}{"orange", 400}, 160 | } 161 | fmt.Println(len(fruits2)) // => "3" 162 | } 163 | 164 | //--------------------------------------------------- 165 | //配列に要素を追加する 166 | //--------------------------------------------------- 167 | /* 168 | スライスが対象の場合はappendで追加できます。 169 | スライスには容量がありますが、容量を超える場合はメモリ確保も 170 | 同時に行ってくれます。 171 | 172 | スライス同士を結合する場合は、結合される側のスライスに"..."を付記します。 173 | */ 174 | func slice_Append() { 175 | num := []int{1, 2, 3, 4, 5} 176 | num = append(num, 99) 177 | fmt.Println(num) // => "[1 2 3 4 5 99]" 178 | 179 | //unshiftをしたい場合は、うーん、スライス同士の結合で。 180 | num = append([]int{99}, num...) 181 | fmt.Println(num) // => "[99 1 2 3 4 5 99]" 182 | } 183 | 184 | //--------------------------------------------------- 185 | //配列の先頭または末尾から要素を取りだす 186 | //--------------------------------------------------- 187 | /* 188 | スライスの要素を取り除く関数はないので、 189 | 新しいスライスを作るしかなさそうです。 190 | 途中から取り除きたい場合は、 191 | [こちら](http://stackoverflow.com/questions/25025409/delete-element-in-slice-golang) 192 | によると、 193 | ``` 194 | a = append(a[:i], a[i+1:]...) 195 | ``` 196 | のようにすると良いらしいです。 197 | 198 | また、スライス引数は参照渡しなので、本来は関数内で 199 | 変更した内容が呼び出し元にも影響を与えますが、 200 | append等のcapを変更する可能性のある操作については、 201 | 呼び元には影響を与えず、 202 | 変更を加えたければ戻り値で返すかポインタ渡しをすることになるようです。 203 | [こちら](http://jxck.hatenablog.com/entry/golang-slice-internals2) 204 | に詳しいです。ここでは戻り値で返してます。 205 | 206 | あと、Pythonでよくある、スライスのa[:-1]のような負indexは 207 | 非サポートだそうです。残念。 208 | */ 209 | func slice_Pop() { 210 | num := []int{1, 2, 3, 4, 5} 211 | num = append(num, 10) 212 | v, num := pop(num) 213 | fmt.Println(v) // =>"10" 214 | v, num = pop(num) 215 | fmt.Println(v) // =>"5" 216 | fmt.Println(num) //="[1 2 3 4]" 217 | } 218 | 219 | func pop(slice []int) (int, []int) { 220 | ans := slice[len(slice)-1] 221 | slice = slice[:len(slice)-1] 222 | return ans, slice 223 | } 224 | 225 | //--------------------------------------------------- 226 | //部分配列を取りだす 227 | //--------------------------------------------------- 228 | /* 229 | a[0:2]のように取り出すことが出来ます。 230 | rubyの[1..3]みたいな、個数指定はありません。 231 | 232 | 破壊的メソッドはありません。pop()と同様に関数の戻り値で対応します。 233 | スライスは配列へのポインタのようなものなので、コピーの類は、makeで 234 | ポインタを作成してcopy()するのがよいです。 235 | */ 236 | func slice_Slice() { 237 | a := []int{1, 2, 3, 4, 5} 238 | 239 | fmt.Println(a[0:2]) // => "[1 2]" 240 | fmt.Println(a[1:4]) // => "[2 3 4]" 241 | 242 | // 破壊的メソッド 243 | num, a, _ := slice(a, 0, 2) 244 | fmt.Println(num) // =>"[1 2]" 245 | fmt.Println(a) // =>"[3 4 5]" 246 | num, a, _ = slice(a, 1, 3) 247 | fmt.Println(num) // => "[4 5]" 248 | fmt.Println(a) // => "[3]" 249 | 250 | } 251 | 252 | func slice(slice []int, start, end int) ([]int, []int, error) { 253 | if len(slice) < start || len(slice) < end { 254 | return nil, nil, fmt.Errorf("Error") 255 | } 256 | ans := make([]int, (end - start)) 257 | copy(ans, slice[start:end]) 258 | slice = append(slice[:start], slice[end:]...) 259 | return ans, slice, nil 260 | } 261 | 262 | //--------------------------------------------------- 263 | //配列を任意の値で埋める 264 | //--------------------------------------------------- 265 | /* fillのような関数はないので、自前でやるしかありません。 */ 266 | func slice_Fill() { 267 | a := []int{1, 2, 3, 4, 5} 268 | 269 | a, _ = fill(a, 255, 2, 4) 270 | fmt.Println(a) // =>"[1 2 255 255 5]" 271 | a, _ = fill(a, 0, 1, 3) 272 | fmt.Println(a) // =>"[1 0 0 255 5]" 273 | } 274 | 275 | func fill(slice []int, val, start, end int) ([]int, error) { 276 | if len(slice) < start || len(slice) < end { 277 | return nil, fmt.Errorf("Error") 278 | } 279 | for i := start; i < end; i++ { 280 | slice[i] = val 281 | } 282 | return slice, nil 283 | } 284 | 285 | //--------------------------------------------------- 286 | //配列を空にする 287 | //--------------------------------------------------- 288 | /*空にしたいときはnilを代入します。*/ 289 | func slice_Clear() { 290 | a := []int{1, 2, 3, 4, 5} 291 | a = nil 292 | fmt.Println(a) // => "[]" 293 | } 294 | 295 | //--------------------------------------------------- 296 | //配列同士を結合する 297 | //--------------------------------------------------- 298 | /* 299 | appendでスライス同士を結合するには、 300 | ``` 301 | append(a,b...) 302 | ``` 303 | のように記載します。 304 | */ 305 | func slice_Concat() { 306 | a := []int{1, 2, 3, 4, 5} 307 | a = append(a, []int{10, 20}...) 308 | fmt.Println(a) // => [1 2 3 4 5 10 20] 309 | } 310 | 311 | //--------------------------------------------------- 312 | //配列同士の和・積を取る 313 | //--------------------------------------------------- 314 | /* 315 | 集合の概念はなさそうですので、[golang-set](https://github.com/deckarep/golang-set) 316 | を使います。[]interface{}を受け取るようです。集合の内容は順不同みたいですね。 317 | 318 | 和集合はUnion()、積集合はIntersect()で演算できます。 319 | */ 320 | //import set "github.com/deckarep/golang-set" 321 | 322 | func slice_Union() { 323 | a := set.NewSetFromSlice([]interface{}{1, 3, 5, 7}) 324 | b := set.NewSetFromSlice([]interface{}{2, 4, 6, 8}) 325 | fmt.Println(a.Union(b)) // => "Set{8, 5, 7, 1, 3, 2, 4, 6}" 326 | 327 | a = set.NewSetFromSlice([]interface{}{1, 2, 3, 4}) 328 | b = set.NewSetFromSlice([]interface{}{3, 4, 5, 6}) 329 | fmt.Println(a.Union(b)) // => "Set{3, 5, 6, 4, 1, 2}" 330 | 331 | a = set.NewSetFromSlice([]interface{}{1, 3, 5, 7}) 332 | b = set.NewSetFromSlice([]interface{}{2, 4, 6, 8}) 333 | fmt.Println(a.Intersect(b)) // => "Set{}" 334 | 335 | a = set.NewSetFromSlice([]interface{}{1, 2, 3, 4}) 336 | b = set.NewSetFromSlice([]interface{}{3, 4, 5, 6}) 337 | fmt.Println(a.Intersect(b)) // => "Set{4,3}" 338 | 339 | } 340 | 341 | //--------------------------------------------------- 342 | //複数の要素を変更する 343 | //--------------------------------------------------- 344 | /* 345 | ``` 346 | a[0:3] = []int{111, 222, 333} 347 | ``` 348 | のような書き方はできません。 349 | */ 350 | func slice_Replace() { 351 | a := []int{1, 2, 3, 4, 5} 352 | a, _ = replace(a, []int{111, 222, 333}, 0, 2) 353 | fmt.Println(a) //=>"[111 222 333 3 4 5]" 354 | 355 | a, _ = replace(a, []int{444, 555}, 3, 5) 356 | fmt.Println(a) //=>"[111 222 333 444 555 5]" 357 | } 358 | 359 | func replace(slice []int, rep []int, start, end int) ([]int, error) { 360 | if len(slice) < start || len(slice) < end { 361 | return nil, fmt.Errorf("Error") 362 | } 363 | ans := make([]int, len(slice)) 364 | copy(ans, slice) 365 | ans = append(ans[:start], rep...) 366 | ans = append(ans, slice[end:]...) 367 | return ans, nil 368 | } 369 | 370 | //--------------------------------------------------- 371 | //配列の配列をフラットな配列にする 372 | //--------------------------------------------------- 373 | /* 374 | []interface{}をたくさん書くと見難いので、ここではany型と名づけます。 375 | 376 | T型への(成功するか不明な)キャストは、 377 | ``` 378 | b,ok:= a.(T) 379 | ``` 380 | で行えます。okの値次第で処理を変えれば型ごとに違う処理を書けます。 381 | 下の例では、intとanyのみで構成されるanyに対して、int変換が成功したら 382 | 取り出す、という処理を再帰的に行っています。 383 | */ 384 | type any []interface{} 385 | 386 | func slice_Flatten() { 387 | a := any{1, any{2, any{3, 4}, 5}, any{6, 7}} 388 | fmt.Println(a) 389 | result := any{} 390 | result = flatten(a, result) 391 | fmt.Println(result) 392 | } 393 | 394 | func flatten(in, result any) any { 395 | for _, x := range in { 396 | s, ok := x.(int) 397 | if ok { 398 | result = append(result, s) 399 | } else { 400 | result = flatten(x.(any), result) 401 | } 402 | } 403 | return result 404 | } 405 | 406 | //--------------------------------------------------- 407 | //配列をソートする 408 | //--------------------------------------------------- 409 | /* 410 | sortパッケージの使い方は 411 | [こちら](http://qiita.com/Jxck_/items/fb829b818aac5b5f54f7) 412 | が詳しいです。 413 | */ 414 | 415 | //import "sort" 416 | func slice_Sort() { 417 | a := []int{5, 1, 4, 2, 3} 418 | sort.Sort(sort.IntSlice(a)) 419 | fmt.Println(a) // => [1 2 3 4 5] 420 | 421 | s := []string{"Orange", "Apple", "Lemon"} 422 | sort.Strings(s) 423 | fmt.Println(s) // => [Apple Lemon Orange] 424 | } 425 | 426 | //--------------------------------------------------- 427 | //条件式を指定したソート 428 | //--------------------------------------------------- 429 | /* 430 | Len(),Less(),Swap()という3つのメソッドを 431 | 実装したクラスを作れば、独自条件のソートが可能です。 432 | */ 433 | func slice_CaseSort() { 434 | a := People{"Hitoshi,045", "Sizuo,046", "Yoshi,0138"} 435 | sort.Sort(a) 436 | fmt.Println(a) // => "[Yoshi,0138 Hitoshi,045 Sizuo,046]" 437 | } 438 | 439 | type Person string 440 | 441 | type People []Person 442 | 443 | func (p People) Len() int { 444 | return len(p) 445 | } 446 | 447 | func (p People) Swap(i, j int) { 448 | p[i], p[j] = p[j], p[i] 449 | } 450 | 451 | func (p People) Less(i, j int) bool { 452 | xi := strings.Split(string(p[i]), ",") 453 | xj := strings.Split(string(p[j]), ",") 454 | return xi[1] < xj[1] 455 | } 456 | 457 | //--------------------------------------------------- 458 | //配列の配列を任意の要素でソートする 459 | //--------------------------------------------------- 460 | /* 461 | ほとんど[こちら](http://qiita.com/Jxck_/items/fb829b818aac5b5f54f7)の丸写しですが。 462 | 463 | 基底クラスを作り、そのクラスを要素に持つstructを作ると、親クラスのメソッドが引き継がれるのですね。 464 | ここはちょっとわかりにくい。。 465 | */ 466 | func slice_SortAnyColumn() { 467 | ar := NSslice{ 468 | NS{2, "b"}, 469 | NS{3, "a"}, 470 | NS{1, "c"}, 471 | } 472 | 473 | sort.Sort(ByN{ar}) 474 | fmt.Println(ar) // => "[{1 c} {2 b} {3 a}]" 475 | 476 | sort.Sort(ByS{ar}) 477 | fmt.Println(ar) // => "[{3 a} {2 b} {1 c}]" 478 | } 479 | 480 | // 基本クラス 481 | type NS struct { 482 | Num int 483 | Str string 484 | } 485 | 486 | type NSslice []NS 487 | 488 | func (n NSslice) Len() int { 489 | return len(n) 490 | } 491 | 492 | func (n NSslice) Swap(i, j int) { 493 | n[i], n[j] = n[j], n[i] 494 | } 495 | 496 | // 数字昇順でソートするクラス 497 | type ByN struct { 498 | NSslice 499 | } 500 | 501 | func (n ByN) Less(i, j int) bool { 502 | return n.NSslice[i].Num < n.NSslice[j].Num 503 | } 504 | 505 | // 文字でソートするクラス 506 | type ByS struct { 507 | NSslice 508 | } 509 | 510 | func (n ByS) Less(i, j int) bool { 511 | return n.NSslice[i].Str < n.NSslice[j].Str 512 | } 513 | 514 | //--------------------------------------------------- 515 | //配列を逆順にする 516 | //--------------------------------------------------- 517 | /* 518 | sort.Reverse()が使えます。ソートせずに逆順にするのはなさそう。 519 | */ 520 | func slice_Reverse() { 521 | a := []int{5, 1, 4, 2, 3} 522 | sort.Sort(sort.Reverse(sort.IntSlice(a))) 523 | fmt.Println(a) // => "[5,4,3,2,1]" 524 | } 525 | 526 | //--------------------------------------------------- 527 | //指定した位置の要素を取り除く 528 | //--------------------------------------------------- 529 | func slice_Delete() { 530 | a := []int{5, 1, 4, 2, 3} 531 | d := 0 532 | 533 | d, a, _ = delete(a, 0) 534 | fmt.Println(d) // => "5" 535 | fmt.Println(a) // => "[1 4 2 3]" 536 | 537 | d, a, _ = delete(a, 1) 538 | fmt.Println(d) // => "4" 539 | fmt.Println(a) // => "[1 2 3]" 540 | 541 | } 542 | 543 | func delete(slice []int, i int) (int, []int, error) { 544 | ret := slice[i] 545 | if len(slice) < i || len(slice) < i { 546 | return 0, nil, fmt.Errorf("Error") 547 | } 548 | ans := make([]int, len(slice)) 549 | copy(ans, slice) 550 | 551 | ans = append(slice[:i], slice[(i+1):]...) 552 | 553 | return ret, ans, nil 554 | } 555 | 556 | //--------------------------------------------------- 557 | //一致する要素を全て取り除く 558 | //--------------------------------------------------- 559 | /* 560 | [こちら](http://ymotongpoo.hatenablog.com/entry/2015/05/20/143004)でご指摘頂きました。ありがとうございます。 561 | 562 | */ 563 | func slice_DeleteAll() { 564 | a := []string{"apple", "orange", "lemon", "apple", "vine"} 565 | 566 | str, a, err := delete_strings(a, "apple") 567 | fmt.Println(str) // => "apple" 568 | fmt.Println(a) // => "[orange lemon vine]" 569 | fmt.Println(err) // => "" 570 | 571 | str, a, err = delete_strings(a, "apple") 572 | fmt.Println(str) // => "" 573 | fmt.Println(a) // => "[orange lemon vine]" 574 | fmt.Println(err) // => "Couldn't find" 575 | } 576 | 577 | func delete_strings(slice []string, s string) (string, []string, error) { 578 | ret := make([]string, len(slice)) 579 | i := 0 580 | for _, x := range slice { 581 | if s != x { 582 | ret[i] = x 583 | i++ 584 | } 585 | } 586 | if len(ret[:i]) == len(slice) { 587 | return "", slice, fmt.Errorf("Couldn't find") 588 | } 589 | return s, ret[:i], nil 590 | } 591 | 592 | //--------------------------------------------------- 593 | //配列から重複した要素を取り除く 594 | //--------------------------------------------------- 595 | /* 596 | これも[golang-set](https://github.com/deckarep/golang-set) 597 | を使います。 598 | */ 599 | //import set "github.com/deckarep/golang-set" 600 | 601 | func slice_Uniq() { 602 | a := []interface{}{30, 20, 50, 30, 10, 10, 40, 50} 603 | as := set.NewSetFromSlice(a) 604 | fmt.Println(as) // => Set{30,20,50,10,40} 605 | 606 | s := []interface{}{"/tmp", "/home/", "/etc", "/tmp"} 607 | ss := set.NewSetFromSlice(s) 608 | fmt.Println(ss) // =>Set{/tmp, /home/, /etc} 609 | } 610 | 611 | //--------------------------------------------------- 612 | //配列から指定条件を満たす要素を取り除く 613 | //--------------------------------------------------- 614 | /* 615 | 条件をいろいろ変えて処理をしたい場合は、無名関数を作って 616 | 関数渡しするのがよいでしょう。 617 | */ 618 | func slice_CaseDelete() { 619 | a := []int{30, 100, 50, 80, 79, 40, 95} 620 | 621 | f0 := func(x int) bool { return x < 80 } 622 | fmt.Println(reject_map(f0, a)) // => "[100 80 95]" 623 | 624 | f1 := func(x int) bool { return x < 90 } 625 | fmt.Println(reject_map(f1, a)) // => "[100 95]" 626 | } 627 | 628 | // sから、f(x)==true なxを取り除く (f(x)==falseなxの配列を返す) 629 | func reject_map(f func(s int) bool, s []int) []int { 630 | ans := make([]int, 0) 631 | for _, x := range s { 632 | if f(x) == false { 633 | ans = append(ans, x) 634 | } 635 | } 636 | return ans 637 | } 638 | 639 | //--------------------------------------------------- 640 | //配列から指定条件を満たす要素を抽出する 641 | //--------------------------------------------------- 642 | /* 643 | 条件をいろいろ変えて処理をしたい場合は、無名関数を作って 644 | 関数渡しするのがよいでしょう。 645 | */ 646 | func slice_CaseSelect() { 647 | a := []int{1, 2, 3, 4} 648 | f0 := func(x int) bool { return (x%2 == 0) } 649 | fmt.Println(select_map(f0, a)) // => [2 4] 650 | } 651 | 652 | // sから、f(x)==true なxを返す 653 | func select_map(f func(s int) bool, s []int) []int { 654 | ans := make([]int, 0) 655 | for _, x := range s { 656 | if f(x) == true { 657 | ans = append(ans, x) 658 | } 659 | } 660 | return ans 661 | } 662 | 663 | //--------------------------------------------------- 664 | //配列中の要素を探す 665 | //--------------------------------------------------- 666 | /* 667 | ``` 668 | type any []interface{} 669 | ``` 670 | でany型を設定してあるとします。 671 | 672 | うーん、、やはり複雑な配列の処理はrubyみたいにはいかないですね。。 673 | */ 674 | func slice_Search() { 675 | a := any{"apple", 10, "orange", any{"lemon", "vine"}} 676 | 677 | i, err := index(a, any{"apple"}) 678 | fmt.Println(i) // => "0" 679 | fmt.Println(err) // => "" 680 | 681 | i, err = index(a, any{10}) 682 | fmt.Println(i) // => "1" 683 | fmt.Println(err) // => "" 684 | 685 | i, err = index(a, any{"fruit"}) 686 | fmt.Println(i) // => "-1" 687 | fmt.Println(err) // => "Couldn't find" 688 | 689 | } 690 | 691 | // aにqueryが見つかればindexを返します。 692 | // とりあえずstringとintにしか対応してません。。 693 | func index(a, query any) (int, error) { 694 | v, ok := query[0].(string) 695 | vi := -1 696 | if !ok { 697 | vi, ok = query[0].(int) 698 | if !ok { 699 | return -1, fmt.Errorf("Only string/int query is supported.") 700 | } 701 | } 702 | 703 | for i, x := range a { 704 | xs, ok := x.(string) 705 | if ok { 706 | if xs == v { 707 | return i, nil 708 | } 709 | } else { 710 | xi, ok := x.(int) 711 | if ok { 712 | if xi == vi { 713 | return i, nil 714 | } 715 | } 716 | } 717 | } 718 | return -1, fmt.Errorf("Couldn't find") 719 | } 720 | 721 | //--------------------------------------------------- 722 | //配列の配列を検索する 723 | //--------------------------------------------------- 724 | /* 725 | うーんまあ愚直に書きましょうか。。 726 | */ 727 | 728 | func slice_Assoc() { 729 | a := []interface{}{ 730 | []interface{}{"apple", 100}, 731 | []interface{}{"vine", 500}, 732 | []interface{}{"orange", 300}, 733 | } 734 | 735 | fmt.Println(assoc(a, "apple")) // => "[apple 100]" 736 | fmt.Println(assoc(a, "orange")) // => "[orange 300]" 737 | fmt.Println(assoc(a, "peer")) // => "[]" 738 | } 739 | 740 | func assoc(a []interface{}, s string) []interface{} { 741 | ans := make([]interface{}, 0) 742 | for _, x := range a { 743 | xs, _ := x.([]interface{}) 744 | v := xs[0].(string) 745 | if v == s { 746 | ans = append(ans, xs...) 747 | } 748 | } 749 | return ans 750 | } 751 | 752 | //--------------------------------------------------- 753 | //配列の各要素にブロックを実行し配列を作成する 754 | //--------------------------------------------------- 755 | /* 756 | ブロックのような記法がないので愚直にやるしかないです。 757 | */ 758 | func slice_Block() { 759 | a := []int{10, 20, 30, 40, 50} 760 | 761 | b := make([]int, len(a)) 762 | copy(b, a) 763 | 764 | for i, x := range a { 765 | b[i] = x * 10 766 | } 767 | fmt.Println(b) // => "[100 200 300 400 500]" 768 | fmt.Println(a) // => "[10 20 30 40 50]" 769 | } 770 | 771 | //--------------------------------------------------- 772 | //配列の各要素に対して繰り返しブロックを実行する 773 | //--------------------------------------------------- 774 | /* こちらも同様。愚直にやるしかないです。*/ 775 | func slice_Block2() { 776 | a := []string{"Taro", "Hanako", "Ichiro"} 777 | for _, x := range a { 778 | fmt.Println("Hello,", x) 779 | } 780 | // => "Hello, Taro" 781 | // => "Hello, Hanako" 782 | // => "Hello, Ichiro" 783 | } 784 | 785 | //--------------------------------------------------- 786 | //配列の要素の和を求める 787 | //--------------------------------------------------- 788 | func slice_Sum() { 789 | a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 790 | sum := 0 791 | for _, x := range a { 792 | sum += x 793 | } 794 | fmt.Println(sum) // => "55" 795 | } 796 | 797 | //--------------------------------------------------- 798 | //配列の要素をランダムに抽出する 799 | //--------------------------------------------------- 800 | // import "time" 801 | // import "math/rand" 802 | func slice_Choice() { 803 | a := []int{1, 2, 3} 804 | fmt.Println(choice(a)) 805 | fmt.Println(choice(a)) 806 | } 807 | 808 | func choice(s []int) int { 809 | rand.Seed(time.Now().UnixNano()) 810 | i := rand.Intn(len(s)) 811 | return s[i] 812 | } 813 | 814 | //--------------------------------------------------- 815 | //複数の配列を同時に動かす 816 | //--------------------------------------------------- 817 | 818 | func slice_ThreeItems() { 819 | fruits := []string{"mango", "apple", "orange"} 820 | prices := []int{200, 120, 100} 821 | counts := []int{5, 10, 12} 822 | 823 | for i, _ := range fruits { 824 | fmt.Println(fruits[i], prices[i], counts[i], prices[i]*counts[i]) 825 | } 826 | //=> "mango 200 5 1000" 827 | //=> "apple 120 10 1200" 828 | //=> "orange 100 12 1200" 829 | } 830 | 831 | //--------------------------------------------------- 832 | //二次元,三次元の座標の配列の成分ごとの最大,最小を求める 833 | //--------------------------------------------------- 834 | /* 835 | matrix.goのColCopy(), RowCopy()で指定行・列の配列を取り出せます。 836 | */ 837 | // import matrix "github.com/skelterjohn/go.matrix" 838 | 839 | func slice_MatMax() { 840 | a, _ := matrix.ParseMatlab("[1 5;8 4;2 9;4 3]") 841 | x := a.ColCopy(0) // => [1 8 2 4] 842 | y := a.ColCopy(1) // => [5 4 9 3] 843 | fmt.Println(max(x)) // => "8" 844 | fmt.Println(max(y)) // => "9" 845 | } 846 | 847 | func max(a []float64) float64 { 848 | max := a[0] 849 | for _, i := range a { 850 | if i > max { 851 | max = i 852 | } 853 | } 854 | return max 855 | } 856 | 857 | //--------------------------------------------------- 858 | // 配列 859 | //--------------------------------------------------- 860 | func Tips_slice() { 861 | 862 | slice_Define() // プログラムで配列を定義する 863 | slice_SliceOfSlice() // m x n 行列の形で配列の配列を初期化する 864 | slice_Join() // 配列要素をカンマ区切りで出力する 865 | slice_Count() //配列の要素数を取得する 866 | slice_Append() //配列に要素を追加する 867 | slice_Pop() //配列の先頭または末尾から要素を取りだす 868 | slice_Slice() //部分配列を取りだす 869 | slice_Fill() //配列を任意の値で埋める 870 | slice_Clear() //配列を空にする 871 | slice_Concat() //配列同士を結合する 872 | slice_Union() //配列同士の和・積を取る 873 | slice_Replace() //複数の要素を変更する 874 | slice_Flatten() //配列の配列をフラットな配列にする 875 | slice_Sort() //配列をソートする 876 | slice_CaseSort() //条件式を指定したソート 877 | slice_SortAnyColumn() //配列の配列を任意の要素でソートする 878 | slice_Reverse() //配列を逆順にする 879 | slice_Delete() //指定した位置の要素を取り除く 880 | slice_DeleteAll() //一致する要素を全て取り除く 881 | slice_Uniq() //配列から重複した要素を取り除く 882 | slice_CaseDelete() //配列から指定条件を満たす要素を取り除く 883 | slice_CaseSelect() //配列から指定条件を満たす要素を抽出する 884 | slice_Search() //配列中の要素を探す 885 | slice_Assoc() //配列の配列を検索する 886 | slice_Block() //配列の各要素にブロックを実行し配列を作成する 887 | slice_Block2() //配列の各要素に対して繰り返しブロックを実行する 888 | slice_Sum() //配列の要素の和を求める 889 | slice_Choice() //配列の要素をランダムに抽出する 890 | slice_ThreeItems() //複数の配列を同時に動かす 891 | slice_MatMax() //二次元,三次元の座標の配列の成分ごとの最大,最小を求める 892 | 893 | } 894 | --------------------------------------------------------------------------------