Go 我がutility関数

3 min read読了の目安(約3000字

初めに

最近個人開発でgoを使っています。goは書いていて楽しいですね(語彙力)。
webフレームワーク、ORMを使わず、さらに極力3rdパーティー系のライブラリを使用せず開発速度を多少犠牲にして楽しんでいます。

そこで自分が個人的に使っているGoの汎用的な関数を紹介します。
* Goは完全に独学故かなり怪しいところとかあると思うので、コメント等でご指摘等してくださると非常にありがたいです。

ランダム文字列生成

import (
    "math/rand"
    "time"
)

// 使用する文字列を定義
const slugLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"

// 引数nを渡してあげることで文字の長さを変えられます
func GenRandSlug(n int) string {
    b := make([]byte, n)
    rand.Seed(time.Now().UnixNano())
    for i := range b {
	b[i] = slugLetters[rand.Intn(len(slugLetters))]
    }
    return string(b)
}

null生成

goはnullの概念がなく基本的に値が渡ってこなければプリミティブ型のデフォルト値が入るので、nullをdbにinsertしたいときとかに使っています。
以下のコードではstring型のデフォルト値であるblankが入ってくればnilを返してくれます

// string
func NullString(s string) *string {
    if s == "" {
        return nil
    }
    return &s
}

素直にgureguさんのguregu/nullを使っちゃった方が手っ取り早いかもしれない...
それにjsonでpostする場合にはtypeの定義の際にomitemptyを使って

type Sample struct {
    FieldA string `json:"field_a"`
    FieldB string `json:"field_b"`
    // omitemptyを使うとプリミティブ型のデフォルトに対してはnullが割り当てられる
    NullableA string `json:"nullable_a,omitempty"`
}

とやってしまった方が手っ取り早いので書いといてなんですが、正直そこまで出番はありません...

cookie

クッキーを設定する関数

set cookie

import "net/http"

func MySetCookie(w http.ResponseWriter, key string, value, string, age int) bool {
    cookie := http.Cookie{
        Name: key,
	Value: value,
	Path: "/",
	Domain: os.Getenv("MY_DOMAIN"),
	MaxAge: age,
	SameSite: http.SameSiteNoneMode,
	Secure: true,
	HttpOnly: true,
    }
    http.SetCookie(w, cookie)
    return true
}

クッキーを削除する関数

ここが少し面倒です。
goにはcookieを削除する関数がないので、MaxAgeを0や負の値にすることで削除します。

import "net/http"

func DestroyCookie(w http.ResponseWriter, key string) bool {
    cookie := &http.Cookie{
        Name: key,
	Value: "",
	Path: "",
	Domain: os.Getenv("MY_DOMAIN"),
	MaxAge: -1, // ココが肝!!
	SameSite: http.SameSiteNoneMode,
	Secure: true,
	HttpOnly: true,
    }
    http.SetCookie(w, cookie)
    return true
}

メール送信

件名、本文、宛先を渡すと送信してくれます

import (
	"net/smtp"
	"os"
)

func BaseSendMail(subject string, message string, to string) error {
    smtpAuth := smtp.PlainAuth(
	"",
	os.Getenv("EMAIL_HOST_USER"),
	os.Getenv("EMAIL_HOST_PASS"),
	os.Getenv("EMAIL_HOST"),
    )

    return smtp.SendMail(
	os.Getenv("EMAIL_HOST")+":"+os.Getenv("EMAIL_PORT"),
	smtpAuth,
	os.Getenv("EMAIL_HOST_USER"),
	[]string{to},
	[]byte(
	    "To: "+to+"\r\n"+ // headerはkeyごとに改行するルール!!
	    "From: "+os.Getenv("EMAIL_HOST_USER")+"\r\n"+ // 0612追記
	    "Subject: "+subject+"\r\n"+
	    "Content-Type: text/plain; charset=\"utf-8\""+"\r\n"+
	    "\r\n"+ // headerとbodyとの間は2行空けるルール!!
	    message,
	    ),
    )
}

0612追記
headerにFromを追加しました。
これがないと受け手がgmialとかの場合弾かれてしまいます。

デフォルト値付き環境変数

環境変数に対象のkeyがあればその値を、無ければdefault値を返す関数

import "os"

func GetenvOrDefault(key string, defa string) string {
    if val, ok := os.LookupEnv(key); ok {
        return val
    }
    return defa
}

// 使い方
var MyName = GetenvOrDefault("MY_NAME", "maru")

続く

今後も追加更新等していこうと思います