- 1. オブジェクト詰め替え対策の一つ — interface利用(golang)
- 2. 【Go】gormでテーブル名と構造体の名前が違う時のtips
- 3. [Golang] [標準logライブラリ] GCPの構造化ログにX-Cloud-Trace-ContextのtraceIdをセットする
- 4. Go の Gorm 使う
- 5. goでutf8メールを送信する
- 6. ポインタについて
- 7. GoでSQLのSELECTをする
- 8. 【Go】”空構造体”の表し方
- 9. Btreeの実装例(golang)
- 10. 漸化式アルゴリズムサンプル(golang)
- 11. [Go] Structの子要素を親要素のポインタで変更できるのか
- 12. # 【Go】チョットわかるインタフェース
- 13. デンソークリエイトプログラミングコンテスト2022(AtCoder Beginner Contest 239) 参戦記
- 14. [Golang] enumを使いたい ~ structでも定数定義できるぞ
- 15. Ubnutu20.04.3 LTSにGo言語の開発環境を構築する (Golang + VSCode+Ubuntu)
- 16. 【Go】http.ResponseWriterのメソッドw.Header().Add()が効かない
- 17. [Golang] Cloud Runで構造化ログを出力できるように実装してみた
- 18. GolangにORM導入(go-pg migration編)
- 19. 【Go言語】time.Timeをjsonでunixtimeを返しつつ、time.Timeの型でGCP/DataStoreに保存する
- 20. Goの環境変数読み出しについて
オブジェクト詰め替え対策の一つ — interface利用(golang)
ORM層とdomain層とデータ受け渡しをする場合、オブジェクト詰め替えが頻繁に発生することで、以下のデメリット・不便が感じている:
– コーディング作業がめんどくさい
– 詰め替え漏れ故のバグ
– 詰め替え処理自体の処理コストはどうかとの心配これで試した対策の一つは interface利用のことです。
詳細はあとで…
【Go】gormでテーブル名と構造体の名前が違う時のtips
Go難しいです。gormは「なんでやねん」と思うことが多いです。
元Railsエンジニアには早すぎた技術なのかもしれません?[Many To Many](https://gorm.io/ja_JP/docs/many_to_many.html)周りの公式の記事が少しわかりにくくて、tipsを書いておきます
# Many To Many (many2many)
gormでは`Preload()`する際に、構造体のフィールドのタグ(`reflect.StructTag`)を仕込むことで、中間テーブルを簡単にORM側に理解させることができます。## 普通の書き方
gorm内部的には、`Field`という構造体で`TagSettings map[string]string`で値を持っていて、全部大文字に変換してるので`map[MANY2MANY:many2many:user_languages]`という感じで保存してあります“`go
// usersテーブル
type User struct {
ID uint
Languages []*Languag
[Golang] [標準logライブラリ] GCPの構造化ログにX-Cloud-Trace-ContextのtraceIdをセットする
## やったこと
前回の記事で下記の課題があった。それを改善したのが本記事の内容。
> サービス運用では同時に複数のアクセスが考えられるため、traceId等でログを追跡できるようにする必要があります。アクセスがたまにしかないようなフェーズではいいかもしれないけど、X-Cloud-Trace-Contextを使用してリクエストとログを一意にできるようにすることは必須だと思うので今後やる。
https://qiita.com/t_morimori777/items/7040b6ea025db4e54630
## はてなブログに掲載しています。
https://moritomo7315.hatenablog.com/entry/go-traceid-logging
Go の Gorm 使う
# はじめに
`Go`を勉強し始めたということで、`O/Rマッパー`も体験しておきます。
今回は、[Go で API 作る](https://qiita.com/pure-adachi/items/47dca38f5508c42f35b3)の続きとして、`Gorm`を入れて試してみたいと思います。
# 早速作ってみる
https://github.com/pure-adachi/go-sample-api-server
今回もこれをベースに組み込んでいきます。
[Go で API 作る](https://qiita.com/pure-adachi/items/47dca38f5508c42f35b3)の続きなので、API部分は`gin`を使います。
※`gin`の使い方は、上記Qiita記事で紹介しているので割愛します。# Gorm を取得する
`Docker`で開発しているので、`docker compose`コマンドとなります。
`DB`は`PostgreSQL`を使ってみます。“`sh
$ docker compose run –rm back go g
goでutf8メールを送信する
Goでメールを送信することは簡単です。`net/smtp`の`SendMail()`で送信できます。しかし、これは平文の送信に限った話です。
マルチバイト文字である日本語を平文のまま送信してしまうと、メーラーによっては文字化けが発生します。よって、utf8エンコーディングしてから送信する必要が出てきます。
メールを送信するには、お決まりのインターネットメッセージフォーマットを守る必要があります。そこで決まっているのが、 [RFC2822](https://datatracker.ietf.org/doc/html/rfc2822) という文書です。ここで特に気にしないといけないのが、一行あたりの文字数です。翻訳してみると、
>There are two limits that this standard places on the number of characters in a line. Each line of characters MUST be no more than 998 characters, and SHOULD be no more than 78 cha
ポインタについて
最近Goを触り始めました。右も左も分からない状況ですが、今日学んだことをアウトプットしていきます。
## ポインタ
めちゃ大事そうだったのでまとめようとおもいます。まず、これを理解するためには**アドレス**を理解しなければなりません。
コンピュータにはメモリという作業場があって、変数はこのメモリに格納されているんですね。その格納されている場所をアドレスというんです。Goではアドレスをポインタと呼んでいます。
つまり、アドレス=ポインタ
実際にポインタを取得してみましょう
“`test.go
package mainimport “fmt”
func main() {
name := “what is golang?”
fmt.Println(&name)
}=> 0xc000042230
“`
Printlnの後に、**&変数名**と書くことでポインタを取得できます。
それでは今度はポインタを変数に代入してみましょう。“`test.go
package mainimport “fmt”
func main() {
name := “what is
GoでSQLのSELECTをする
Goの標準パッケージを使ってデータベースに接続してSELECT文を実行する方法を調べたので、簡単にまとめる。
## 準備
### 1. パッケージのインポート
抽象的な操作を提供する標準パッケージの`database/sql`と、実際にMySQLに対する操作が実装されている`go-sql-driver/mysql`をインポートする。他のパッケージは必要に応じて。“`go
import (
“database/sql”
“fmt”
“log”
“time”_ “github.com/go-sql-driver/mysql”
)
“`### 2. 結果を代入する変数の宣言
“`go
var (
id *int
name *string
)
“`### 3. sql.DBオブジェクトの生成
使用するドライバやデータベースの認証情報を渡して`sql.DB`オブジェクトを生成する。この時点ではまだDBへのコネクションは作られておらず、コネクションは実際にクエリを発行する時に`database.sql`パッケージが勝手に生成・破棄してくれるらしい。
【Go】”空構造体”の表し方
# 初めに結論
**空の構造体(struct)は、「struct{}」と表します。**
interface{}みたいなものですね。空構造体は、
– 空の構造体は**メモリサイズが 0である**
– 空の構造体は**属性**を持たない
– 空の構造体は**同じアドレス**を示すといった特性を持ちます。
# 構造体(struct)とは?
**「type [定義する名前] struct」** のように使用します。
“`go
// 「Person」という名前の構造体(struct)
// この場合、NameとAgeという「フィールド」を持っています。
type Person strcut {
Name string
Age int
}
“`
「フィールド」はpytonなどで使われるclassでいうところの、コンストラクタのようなものです。そして、このフィールドを何も持たない、つまり”空”であるため、
“`go
struct{}
“`この書き方で表せるのですね〜。
##### ちなみに使い方の実例はこんな感じです。
“`go
type (
Per
Btreeの実装例(golang)
#何が書いてあるか
BtreeのGoでの実装例。備忘録。##
“`go
// 節・葉に持たせる機能のインターフェース
type Item interface {
Eq(Item) bool
Less(Item) bool
}
// インターフェースの実装
type Int int
func (n Int) Eq(m Item) bool {
return n == m.(Int)
}
func (n Int) Less(m Item) bool {
return n < m.(Int) } // 節・葉の構造 type Node struct { item Item left, right *Node } // 節・葉の作成 func newNode(x Item) *Node { p := new(Node) p.item = x return p } // 二分木 type Tree struct { root *Node } // 二分木の生成 func newTree() *Tree {
漸化式アルゴリズムサンプル(golang)
#何が書いてあるか
漸化式のアルゴリズムのGo版。備忘録用。## 適用ケース
N段の階段をA段飛ばし、B段飛ばしで登ったときの、各段ごとにとれる登るパターン数を計算する。 など
上記ケースでのコード例)“`go
package main
import “fmt”
func main(){
dp:=make([]int,N+1)
dp[0]=1for i:=1;i<=N;i++ { dp[i]=0 if i>=A {
dp[i]=dp[i]+dp[i-A]
}
if i>=B {
dp[i]=dp[i]+dp[i-B]
}
}
// ここから続く5行は、頂上手前で飛ばす段数よりも残り段数が少ない場合には、頂上に到達させるとする場合のルート数の計算。
end:=0
for i:=N-1;i>=N-A+1;i– {
end+=dp[i]
}
dp[N]+=end
[Go] Structの子要素を親要素のポインタで変更できるのか
## はじめに
Structのポインタを渡して中身を変更するときに子要素のStructの中身も変更できるのか分からなかったので検証しました。バージョン:Go 1.16
## 検証
“`go
package mainimport “fmt”
type Child struct {
AAA string
}type Parent struct {
BBB string
Child Child
}func changeParent(p *Parent) {
p.BBB = “ccc”
}func changeChild(p *Parent) {
p.Child.AAA = “ddd”
}func changeChildDirect(c *Child) {
c.AAA = “eee”
}func main() {
c := Child{
AAA: “aaa”,
}p := Parent{
BBB: “bbb”,
Child: c,
}fmt.Println(p)
// {bbb {aaa}}change
# 【Go】チョットわかるインタフェース
自分がインタフェースについて理解したことをまとめます。僕と同じ初学者の理解を手助けできればうれしいです。Gopher道場が提供してくれている動画やスライド、書籍「プログラミング言語Go」を参考にしています。
## 最初にこの記事の結論
以下のようになりました。タイトルの通りちょっとしかわかりませんでした。
> インタフェースの使い方はちょっと分かったけど、メリットを実感できる使い方まではわからなかった。
>## はじめに用語を整理する
最初に用語を整理します。現時点は「へえ」くらいの温度感でいいと思うのでざっくり意味を理解することが大切だと思います。
| メソッド | レシーバと紐づけられた関数 |
| — | — |
| インタフェース | 抽象化を実現するメソッドの集まり |## 前段階にメソッドの理解を深める
本題はインタフェースの理解を深めることですが、前段階としてメソッドの理解を深める必要があると感じています。以下はメソッドを使用した簡単なコードです。一緒に見ていきましょう。
“`go
package mainimport (
“fmt
デンソークリエイトプログラミングコンテスト2022(AtCoder Beginner Contest 239) 参戦記
# デンソークリエイトプログラミングコンテスト2022(AtCoder Beginner Contest 239) 参戦記
## [ABC239A – Horizon](https://atcoder.jp/contests/abc239/tasks/abc239_a)
2分で突破. 書くだけ.
“`python
from math import sqrtH = int(input())
print(sqrt(H * (12800000 + H)))
“`## [ABC239B – Integer Division](https://atcoder.jp/contests/abc239/tasks/abc239_b)
4分半で突破. 試したら Python の除算そのままであれってなった.
“`python
X = int(input())print(X // 10)
“`## [ABC239C – Knight Fork](https://atcoder.jp/contests/abc239/tasks/abc239_c)
9分で突破. 2点の周
[Golang] enumを使いたい ~ structでも定数定義できるぞ
元々Javaエンジニアの私ですが、最近Goを趣味で使い始めたのでメモ程度に。
今回はJavaでよく使うenumをGoでもそれっぽく使う方法を残しておきます。## まずは基本的な使い方
よくGoogleで検索して見かけるやつ“`hoge1.go
package constant// 自動で採番してくれる
const (
HOGE1_1_1 = iota // 0
HOGE1_1_2 = // 1
HOGE1_1_3 = // 2
)// 1始まりにしたい
const (
HOGE1_2_1 = 1
HOGE1_2_2 = 2
HOGE1_2_3 = 3
)// 文字列で定義したい
const (
HOGE1_3_1 = “hoge1”
HOGE1_3_2 = “hoge2”
HOGE1_3_3 = “hoge3”
)// 基本型をベースにした独自の型で定義したい
type HOGE uint8
const (
HOGE1_4_1 HOGE = 1
HOGE1_4_2 HOGE = 2
HOGE1_4_3 HOGE =
Ubnutu20.04.3 LTSにGo言語の開発環境を構築する (Golang + VSCode+Ubuntu)
今更ながら、Ubnutu20.04.3にGoをインストールします。
## インストールするマシンについて
### os情報“`bash
user@machine:~/gotrain$ cat /etc/os-release
NAME=”Ubuntu”
VERSION=”20.04.3 LTS (Focal Fossa)”
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME=”Ubuntu 20.04.3 LTS”
VERSION_ID=”20.04″
HOME_URL=”https://www.ubuntu.com/”
SUPPORT_URL=”https://help.ubuntu.com/”
BUG_REPORT_URL=”https://bugs.launchpad.net/ubuntu/”
PRIVACY_POLICY_URL=”https://www.ubuntu.com/legal/terms-and-policies/privacy-policy”
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
`
【Go】http.ResponseWriterのメソッドw.Header().Add()が効かない
http.ResponseWriterのメソッドHeader().Add()でヘッダーを追加したはずなのに、レスポンスのヘッダーを見ると付与されていない。
単純にw.Header().Addの前に、w.Writeを呼び出していたことが原因だった。順番を逆にすると、想定どおり動作する。
“`go:改修前
func(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte(“Hello, world”))w.Header().Add(“Access-Control-Allow-Origin”, “http://localhost:3000”)
w.Header().Add(“Access-Control-Allow-Headers”, “Content-Type, X-CSRF-Token”)
w.Header().Add(“Access-Control-Allow-Methods”, “POST, OPTIONS”)
w.Header().Add(“Access-Control-Expose-Headers”,
[Golang] Cloud Runで構造化ログを出力できるように実装してみた
## やったこと
* goの標準log出力をGCPの構造化ログのフォーマットで出力するようにしてみた。
* Cloud Runにデプロイして確認してみたところ無事ログが各ログレベルで出力されるようになった。
* 標準logライブラリのファイル名表示などされなくなったが、ログの出力をgrepすれば調査はできるので一旦よしとします。## 課題
* サービス運用では同時に複数のアクセスが考えられるため、traceId等でログを追跡できるようにする必要があります。アクセスがたまにしかないようなフェーズではいいかもしれないけど、`X-Cloud-Trace-Context`を使用してリクエストとログを一意にできるようにすることは必須だと思うので今後やる。
* Cloud loggingなどの仕組みをつかってERRORのログをSlackに通知する仕組みとか作ってみようと思います。## 内容ははてなブログに掲載してます
https://moritomo7315.hatenablog.com/entry/golang-gcp-log-output
GolangにORM導入(go-pg migration編)
#はじめに
GolangのORMであるgo-pgの導入です。本記事ではgo-pgのチュートリアルに沿ってマイグレーションを実行します。
※go-pgは現在メンテナンスモードのため、bunへの移行が推奨されています。今から学ばれている方はbunを利用することをお勧めいたします。私は諸事情があり、あえてgo-pgで開発をしています。#環境情報
PC:Mac(CPUはintel製)
Go:1.17.6 ←Goのver大事。versionは1.16以降をインストールしてください。
開発エディタ:Visual Studio Code#ディレクトリ構成
“`shell:ディレクトリ構成
~/go/src/go-pg-migrate $ tree
.
├── docker-compose.yml
├── examples
│ ├── 1_initial.go
│ ├── 2_add_id.go
│ ├── 3_seed_data.go
│ └── main.go
├── go.mod
└── go.sum1 directory, 7 files
“`#Hands-
【Go言語】time.Timeをjsonでunixtimeを返しつつ、time.Timeの型でGCP/DataStoreに保存する
# 概要
掲題の通りです。
ニッチな内容なので需要ないと思いますが、自分の備忘用としてのpostになります。# 課題
普段、Webサーバー側の開発はGAE/Goを利用しており、特に指定がない限りDBはDatastoreを利用しています。
ただ JSONの取り扱いでよく困るのが `time.Time` の挙動です。
この子、何も指定がない場合は `RFC3339` 形式の文字列としてJSONに格納されます。“`go
import (
“time”
“encoding/json”
)type Hoge struct {
ID int64 `json:”id” datastore:”-“`
Name string `json:”name” datastore:”name”`
CreatedAt time.Time `json:”createdAt” datastore:”createdAt”`
}var hoge := Hoge {
ID : 1,
Name : “te
Goの環境変数読み出しについて
環境変数をセットする際に、いくつかパターンがあるなと思ったのでまとめます。
# 基本
“`:basicEnv.go
package mainimport (
“os”
“fmt”
)func main() {
os.Setenv(“ENV”, “debug”)
env := os.Getenv(“ENV”)
fmt.Println(env)
}
“`# `joho/godotenv`
“`:.env
ENV=debug
“`“`:dotEnv.go
package mainimport (
“os”
“fmt”
“log”
dotenv “github.com/joho/godotenv”
)func main() {
if err := dotenv.Load(); err != nil {
log.Fatalln(err)
}
env := os.Getenv(“ENV”)
fmt.Println(env)
}
“`#