| |
初歩のGo言語
やってみます。
Hello World
最も簡単なHello Worldです。
package main
import (
"fmt"
)
func main(){
fmt.Println("Hello, Go言語 ワールド!")
}
|
UTF-8テキストファイルの読み書き
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main(){
content, err := ioutil.ReadFile("./indata_utf8.txt")
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
fmt.Println(string(content))
err = ioutil.WriteFile("./outdata.txt", content, 0644)
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
}
|
シフトJISのテキストファイルの読み書き
SJISのファイルの読み書きは一気に複雑になります。なんでと言われてもしょうがない。
package main
import (
"fmt"
"log"
"io/ioutil"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/transform"
)
func main(){
s1, err := ioutil.ReadFile("./indata_sjis.txt")
if err != nil { log.Fatal(err) }
// s1はbyte[]なので、string()で変換する必要がある
s2, n, err := transform.String(japanese.ShiftJIS.NewDecoder(), string(s1))
if err != nil { log.Fatal(err) }
fmt.Printf("%d bytes\n", n)
fmt.Println(s2)
s3 := `------
テストの
出力
です。
------
` + s2
s4, n, err := transform.String(japanese.ShiftJIS.NewEncoder(), s3)
if err != nil { log.Fatal(err) }
fmt.Printf("%d bytes\n", n)
// s4はstringなので、byte[]で変換する必要がある
errw := ioutil.WriteFile("./outdata.txt", []byte(s4), 0644)
if errw != nil { log.Fatal(errw) }
}
|
簡単なWebサーバ
まずプログラムを次のように書きます。
package main
import(
"fmt"
"os"
"net/http"
"html/template"
"io/ioutil"
)
func main(){
http.Handle("/", http.HandlerFunc(makePage))
http.ListenAndServe(":9090", nil)
}
func makePage(w http.ResponseWriter, req *http.Request){
content, err := ioutil.ReadFile("indexhtml.txt")
if err != nil {
fmt.Println("テンプレートファイル読み込み失敗", err)
os.Exit(1)
}
templateStr := string(content)
t := template.Must(template.New("sendname").Parse(templateStr))
t.Execute(w, req.FormValue("yourname"))
}
|
このテンプレートファイル "indexhtml.txt" は次のように書きます。
<!DOCTYPE html>
<html lang="ja">
<head><meta charset="UTF-8"></head>
<body>
こんにちは。
{{if .}}
{{ . }} さん
{{else}}
すみません、どちらさまですか
{{end}}
<form action="/" name="form1" method="GET">
<input type="text" size="40" name="yourname" value="" title="名前を入力してください">
<input type="submit" value="送信">
</form>
</body>
</html>
|
Excelファイルを読む
package main
import(
"fmt"
"log"
"github.com/xuri/excelize/v2"
)
func main(){
// ファイルはWriteロックされるがReadロックはされない
// (他のプログラムが開いているExcelファイルでもOpenFileは成功する)
f, err := excelize.OpenFile("./indata.xlsx")
if err != nil { log.Fatal(err) }
defer f.Close()
// モジュールの関数はすべてシートの名前を渡す必要があるので、
// 事前に分からなければシート番号から取得しておく必要がある
// シート番号は0から始まる。1からではないので注意
sheetName := f.GetSheetName(0)
fmt.Println("Sheet Name:" + sheetName)
// C18セルの値を出力
cell, err := f.GetCellValue(sheetName, "C18")
if err != nil { log.Fatal(err) }
fmt.Println(cell)
// セルを(列番号、行番号)で参照する。(行、列)ではないので注意
// また番号は1から開始するので、(7,21)はG21セルの意味になる
cname, err := excelize.CoordinatesToCellName(7, 21)
if err != nil { log.Fatal(err) }
cell, err = f.GetCellValue(sheetName, cname)
if err != nil { log.Fatal(err) }
fmt.Println(cell)
// 全ての行を取得する。特定の行だけを取得する関数はないらしい
rows, err := f.GetRows(sheetName)
if err != nil { log.Fatal(err) }
for y, row := range rows {
if len(row) > 2 && row[2] == "本社" {
fmt.Printf("見つかりました。%d行目\n", y)
fmt.Println("------")
for _, colcell := range row {
fmt.Print(colcell + "\t")
}
fmt.Println("------")
break // 見つけたら即ブレーク
}
}
}
|
Excelファイルに書く
package main
import(
"log"
"github.com/xuri/excelize/v2"
)
func main(){
f := excelize.NewFile()
// NewFile()でSheet1というシートが既に作られている。
// さらにシートを増やすときにNewSheet()を使う
f.NewSheet("新しいシート")
f.SetCellValue("新しいシート", "B3", "Hello World")
f.SetCellValue("新しいシート", "B4", 1234)
f.SetCellValue("新しいシート", "B5", "こんにちは")
err := f.SaveAs("./output/newbook.xlsx")
if err != nil { log.Fatal(err) }
}
|
Excelの計算式を使う
package main
import(
"log"
"github.com/xuri/excelize/v2"
)
func main(){
f := excelize.NewFile()
f.SetCellValue("Sheet1", "B3", 1234)
f.SetCellValue("Sheet1", "B4", 2345)
f.SetCellValue("Sheet1", "B5", 3456)
err := f.SetCellFormula("Sheet1", "C3", "=B3+B4")
if err != nil { log.Fatal(err) }
err = f.SetCellFormula("Sheet1", "C4", "=B4+B5")
if err != nil { log.Fatal(err) }
err = f.SetCellFormula("Sheet1", "C5", "=B4+B5")
if err != nil { log.Fatal(err) }
// 参照先のセルの値を変えてみる
f.SetCellValue("Sheet1", "B5", 3457)
err = f.SaveAs("newbook.xlsx")
if err != nil { log.Fatal(err) }
}
|
Excelのスタイルのサンプル
package main
import(
"time"
"log"
"github.com/xuri/excelize/v2"
)
func main(){
f := excelize.NewFile()
// 列幅と行の高さの設定。列幅は複数を一括して指定可能
f.SetColWidth("Sheet1", "I", "K", 20)
f.SetRowHeight("Sheet1", 3, 50)
f.SetCellValue("Sheet1", "B3", "Hello World")
f.SetCellValue("Sheet1", "B4", 1234)
f.SetCellValue("Sheet1", "B5", "こんにちは")
// 枠線の設定
style, err := f.NewStyle(&excelize.Style {
Border: []excelize.Border {
{Type: "left", Color: "0000FF", Style: 3},
{Type: "right", Color: "00FF00", Style: 4},
{Type: "top", Color: "FF0000", Style: 5},
{Type: "bottom", Color: "FF00FF", Style: 6},
},
})
if err != nil { log.Fatal(err) }
err = f.SetCellStyle("Sheet1", "B3", "E5", style)
// 塗りつぶし
// 色が1要素なのに配列で指定するのはグラデーションにも対応しているから
style, err = f.NewStyle(&excelize.Style {
Fill: excelize.Fill{Type: "pattern", Color:[]string{"FFCCCC"}, Pattern:1},
})
if err != nil { log.Fatal(err) }
err = f.SetCellStyle("Sheet1", "F6", "I8", style)
// 日付の書式
datestr := "2022/05/28 09:10:11"
// Goの文字列型で日付を設定してしまうと、
// Excelの書式を何に設定しても文字列として表示されてしまう
f.SetCellValue("Sheet1", "J4", datestr)
f.SetCellValue("Sheet1", "J5", datestr)
f.SetCellValue("Sheet1", "J6", datestr)
// GoのDateオブジェクトで設定すると、設定したExcel書式で表示される
loc,_ := time.LoadLocation("Asia/Tokyo")
d := time.Date(2022, 5, 28, 9, 10, 11, 0, loc)
f.SetCellValue("Sheet1", "K4", d)
f.SetCellValue("Sheet1", "K5", d)
f.SetCellValue("Sheet1", "K6", d)
// 組み込み書式を使用
style, err = f.NewStyle(&excelize.Style {NumFmt: 15})
if err != nil { log.Fatal(err) }
err = f.SetCellStyle("Sheet1", "J5", "K5", style)
// カスタム書式を使用
// CustomNumFmtは*string型なので一旦変数に入れて&で参照する必要がある
// ちなみにExcelでは月のmmと分のmmを位置関係だけで区別しているらしい
expression := "yyyy/mm/dd hh:mm:ss"
style, err = f.NewStyle(&excelize.Style {CustomNumFmt: &expression})
if err != nil { log.Fatal(err) }
err = f.SetCellStyle("Sheet1", "J6", "K6", style)
err = f.SaveAs("newbook.xlsx")
if err != nil { log.Fatal(err) }
}
|
構造体のサンプル
package main
import(
"fmt"
)
// 各フィールドをカンマなどで区切る必要はない
type person struct {
name string
age int
}
// 構造体の中に別の構造体名だけを書くと、継承っぽい記述ができる
// (fighter.person.nameをfighter.nameとも書ける)
// 「person person」と書いてしまうとこういう記述はできないので注意
type fighter struct {
person
hp int
maxHp int
mp int
maxMp int
}
// 構造体のフィールド値を変更する場合は参照渡しにする必要がある
func (f *fighter) GetDamage(d int){
f.hp -= d
if f.hp < 0 { f.hp = 0 }
}
// これらはフィールドの値を変更しないので、参照渡しは必須ではないが一応統一する
func (p *person) PrintInfo(){
fmt.Printf("%s (%d)\n", p.name, p.age)
}
func (f *fighter) PrintStatus(){
fmt.Printf("%s (%d) %d/%d %d/%d\n", f.name, f.age, f.hp, f.maxHp, f.mp, f.maxMp)
}
// コンストラクタっぽいもの
func NewFighter(name string, age int, maxHp int, maxMp int) fighter {
p := person{ name:name, age:age }
f := fighter{ person: p, maxHp: maxHp, maxMp: maxMp }
f.hp = f.maxHp
f.mp = f.maxMp
return f
}
func main(){
f := NewFighter("Taro", 25, 50, 8)
f.PrintInfo()
f.PrintStatus()
f.GetDamage(14)
f.PrintStatus()
}
|
H2データベースに接続する
最初に以下を実行します。
go get github.com/jmrobles/h2go
H2はServerモードで起動しておく必要があります。
java -cp C:\Wintools\h2\bin\h2-2.2.220.jar org.h2.tools.Server -tcp -ifExists
package main
import (
"database/sql"
"log"
_ "github.com/jmrobles/h2go"
)
func main() {
// ファイルモード(Embeddedモード)では接続できない
//db, err := sql.Open("h2", "stuser:stpass@h2:file://C:/usr/dbms/h2/shiten/stdb")
// 本来のH2のURLではServerを起動した位置からの相対パスでもDBを指定できるはずですが、
// この拡張の場合絶対パスしか指定できないらしい。さらに":"文字がエラーになるので、ドライブも指定できない
db, err := sql.Open("h2", "h2://testuser:testpass@localhost/usr/dbms/h2/shiten/stdb")
if err != nil {
log.Fatalf("Can't connet to H2 Database: %s", err)
}
defer db.Close()
rows, err := db.Query("SELECT SHITEN_CODE, SHITEN_NAME FROM SHITEN ORDER BY SHITEN_CODE")
if err != nil {
log.Printf("Query error: %s", err)
return
}
defer func() {
err = rows.Close()
if err != nil {
log.Printf("Can't close dataset: %s", err)
}
}()
for rows.Next() {
var shitenCode string
var shitenName string
rows.Scan(&shitenCode, &shitenName)
log.Printf("コード: %s,\t名称 : %s", shitenCode, shitenName)
}
log.Printf("Done!!")
}
|
SQLiteデータベースに接続する
最初に以下を実行します。
go get modernc.org/sqlite
package main
import (
"database/sql"
"log"
_ "modernc.org/sqlite"
)
func main() {
// DBファイルのパスが間違っているとなぜか"out of memory(14)"というエラーになるので注意
dbFilePath := "C:/usr/dbms/sqlite3/stdb/stdb"
db, err := sql.Open("sqlite", "file:" + dbFilePath + "?cache=shared")
if err != nil {
log.Fatalf("Can't connect to database: %s", err)
}
defer db.Close()
rows, err := db.Query("SELECT SHITEN_CODE, SHITEN_NAME FROM SHITEN ORDER BY SHITEN_CODE")
if err != nil {
log.Printf("Query error: %s", err)
return
}
defer func() {
err = rows.Close()
if err != nil {
log.Printf("Can't close dataset: %s", err)
}
}()
for rows.Next() {
var shitenCode string
var shitenName string
rows.Scan(&shitenCode, &shitenName)
log.Printf("コード: %s,\t名称 : %s", shitenCode, shitenName)
}
log.Printf("Done!!")
}
|

(first uploaded 2024/09/01 last updated 2024/09/01, URANO398)
|