Go関連のことを調べてみた

Go関連のことを調べてみた

Goの脆弱性診断を定期実行したい(govulncheck-action)

# はじめに
Goプロジェクトのセキュリティを確保するために、定期的な脆弱性診断は必須ですよね。

Goの脆弱性診断を定期実行する仕組みを構築すれば、開発スピードを落とすことなくセキュリティ対策を強化できます。

今回は、[govulncheck-action](https://github.com/marketplace/actions/golang-govulncheck-action)を使って、Goの脆弱性診断を継続的に実行する方法について紹介します。

# GitHub Actionsのワークフロー作成
以下のyamlを.github/workflows配下に追加します。
“`.github/workflows/go_vluncheck_sample.yaml
name: Go Vulnerability Check
on:
# ここで定期実行のための設定をしています
schedule:
– cron: ‘0 23 * * *’ # UTC表記。毎日8時(JST)に実行
jobs:
go_vulncheck:
runs-on: ubuntu-20.04

元記事を表示

Goの正規表現処理をstringsパッケージで代替してBenchmarkを測ってみる

Goの正規表現を標準の [regexp](https://pkg.go.dev/regexp) パッケージで処理すると遅い、という話をしばしば聞きます。
これは [こちらの記事](https://qiita.com/momotaro98/items/09d0f968d44c7027450d) などで紹介されているように、Goの正規表現で採用しているアルゴリズム(Thompson NFA)の都合上、他のアルゴリズムを採用している言語と比較した時、苦手なケースでは遅くなる、というのが実態のようです。

実際のパフォーマンスは、ユースケースに合わせたBenchmarkテストを書いて測りつつ、他の手法と比較してみるのが良さそうです。
今回は、Go標準の [strings](https://pkg.go.dev/strings) パッケージを使ってどの程度代替できるのか、速くなるのか、いくつかのパターンでBenchmarkを測ってみました。

## 実行環境
go version go1.22.5 darwin/arm64

## 前提
Benchmarkの試行回数は少ないので、計測結果に多

元記事を表示

【Go言語】n進数

## はじめに

“`go
func main() {
sum := 100 + 020
fmt.Println(sum)
}
“`

これを実行すると、**120**ではなく、 **116** が出力されます。
Goでは、0から始まる数字は8進数とみなされます。

:::note info
ちなみに余談ですが、javascriptはもっと奇妙な動作をします。気になる方は
[【超難問】絶対に解けないJavaScriptクイズ8選](https://qiita.com/twrcd1227/items/a64c3f22da46ff2c0fbd)
:::

## 2進数(バイナリ)

`0b`、`0B`のprefixつける。(e.g. 0b1010)

以下はビット演算の例。

“`go
func main() {
var a uint8 = 0b1010
var b uint8 = 0b0110

fmt.Printf(“a AND b = %08b\n”, a & b)
fmt.Printf(“a OR b = %08b\n”, a | b)

元記事を表示

【Go言語】Go100Tips1~4をまとめてみた

# はじめに

Go 100 Tipsの 1〜4 をまとめました。

スライドもあります。

また、Tip.3に関しては、別の記事にしました。

https://qiita.com/twrcd1227/items/6e7079d16fd27a7c7d6e

# シャドーイング

シャドーイングとは、異なるスコープで同じ名前の変数が使用されたときに、異なる変数として扱われること。ちなみに、同じスコープ内だと再宣言となり、コンパイラエラーとなります。

“`go
func main() {
n := 1
if true {
n := 999 // シャドウイングされる
fmt.Println(n) // 999
}
fmt.Println(n) // 1
}
“`

`:=`ではなく、代入演算子`=`を使うとシャドウイングされません。

“`go
var n int
func main() {
n := 1
if true {

元記事を表示

Goのヒープとスタックについて

# Goのヒープとスタックについて

## はじめに
Go言語では、メモリ管理が自動的に行われ、プログラマが直接メモリを管理する必要はありません。しかし、ヒープとスタックの違いを理解することは、効率的なプログラムを書くために重要です。この記事では、Goのヒープとスタックについて説明し、それぞれの特徴、利点、注意点について解説します。

## 目次
1. [ヒープとは](#ヒープとは)
2. [スタックとは](#スタックとは)
3. [ヒープとスタックの違い](#ヒープとスタックの違い)
4. [Goにおけるメモリ管理](#goにおけるメモリ管理)
5. [ヒープとスタックの使い分け](#ヒープとスタックの使い分け)
6. [まとめ](#まとめ)

## ヒープとは
ヒープは、動的にメモリを割り当てるための領域です。ヒープに割り当てられたメモリは、プログラムの実行中に動的に確保され、必要がなくなるまで保持されます。ヒープメモリは、ガベージコレクタによって自動的に解放されます。

### 特徴
– **動的メモリ割り当て**: 実行時に必要なメモリを動的に確保します。
– **長寿命**:

元記事を表示

【Go】サーバーを立ててみる

今読んでいる技術書の内容で大事だと思った部分を少しずつまとめていきたいと思います。

今回読んでいる本はこちら
__Goプログラミング実践入門__

この書籍では、フレームワークに頼らず標準ライブラリでweb開発をすることができます。
個人的にフレームワークはブラックボックスが多すぎて面倒であまり好きではない派なので、これを理解できることで理解が深まるのではないかと考え購入しました。

:::note info
この本ではプログラミング言語Goとその標準のライブラリだけを使って、
ゼロからWebアプリケーションを開発するのに必要な事柄を解説します。

ほかのライブラリやその他のトピック(Webアプリケーションのテストやデプロイなど)について解説するページもありますが、Go言語の標準ライブラリのみを用いたWeb開発を解説することがこの本の主目的です。
:::

本記事では、3章で重要だと思った考えや理解しづらかった箇所を説明しています。

# HTTPでサーバーを立てる
まず、3章では以下のように書かれています。

:::note info
net/httpライブラリはhttpサーバー

元記事を表示

【Go】既存のメソッドを追加、変更する方法(Decoratorパターン)

# はじめに
* Decoraterパターンは、オブジェクトの振る舞いを追加 / 変更するための非常に強力なデザインパターンです
* Goには直接的なサポートはありませんが、インターフェースと関数を使うことで、このパターンを実装することができます
* 本記事では、GoでDecoratorパターンを実装する手法の非常にシンプルな例として、メソッドの出力前後に固定のメッセージを追加するデコレータを紹介します

# 対象読者
* Goの関数、メソッド、インターフェースの基礎を理解されている方

# Decoratorパターンとは
* GoFによって定義されたデザインパターンの一つです
* 既存のメソッドを変更せずに、オブジェクトの振る舞いを追加 / 変更することが可能です

https://www.techscore.com/tech/DesignPattern/Decorator

# ステップ1:インターフェース定義
以下のようなPrinterインターフェースと、それを実装するMyPrinter型を定義します。
“`main.go
package main

import “fmt”

元記事を表示

ざっくりGoのチャネルについて

# Goのチャネルについて

## はじめに
Go言語のチャネル(Channel)は、Goroutine間でデータをやり取りするための強力な機能です。チャネルを使用することで、Goroutine間の通信と同期を簡単に実装することができます。この記事では、チャネルの基本的な概念、使い方、利点、注意点について説明します。

## 目次
1. [チャネルとは](#チャネルとは)
2. [チャネルの使い方](#チャネルの使い方)
3. [チャネルの利点](#チャネルの利点)
4. [チャネルの注意点](#チャネルの注意点)
5. [まとめ](#まとめ)

## チャネルとは
チャネルは、Goroutine間でデータを送受信するためのデータ構造です。チャネルは型付きであり、特定のデータ型のみを送受信することができます。チャネルを使用することで、Goroutine間の通信と同期を簡単に実装することができます。

## チャネルの使い方
チャネルの基本的な使い方を以下に示します。

### チャネルの作成
チャネルは `make` 関数を使用して作成します。
“` go
ch := make(ch

元記事を表示

Go + クリーンアーキテクチャにおけるエラーハンドリング戦略

# はじめに
こんにちは!mizukoです!
先日[PaPut](https://paput.io)という個人開発のサービスをβ版としてリリースしました!

その際、今後の個人開発ライフのために基盤作りを行ったのですが、
エラーハンドリングの戦略も検討したので、アウトプットしていきたいと思います!

PaPutについてはぜひ[こちら](https://qiita.com/mizuko_dev/items/5335f93bb3c93f407796)をご覧いただけますと幸いです🤗

# 前提
– プロジェクトはクリーンアーキテクチャの構成
(本記事で紹介するエラーハンドリング方法はどの様な構成でも使えると思いますが、私自身がこの構成でしか運用したことが無いのため、クリーンアーキテクチャを前提とさせていただいています。)

# 戦略
独自のエラーハンドリングにならないよう、シンプルに以下戦略で進めます…!
– errorの管理はプロジェクトルートにerrors/errors.goを作成し、一元管理する
– 全てerror型で扱い、error型をラップして新しい構造体を作るなどは行わな

元記事を表示

CEL(Common Expression Language)でGo言語の構造体を処理

式言語 [CEL(Common Expression Language)](https://github.com/google/cel-spec) の Go 言語用ライブラリとして [cel-go](https://github.com/google/cel-go) があります。

[cel-go](https://github.com/google/cel-go) では、一般的なプリミティブ型に加えて list, map, JSON, Protocol Buffers の型に対応していますが、ソースコードを見る限り Go の構造体も処理できそうだったので試してみました。

# はじめに

基本的に、cel-go は以下の流れで実装します。

1. Environment のセットアップ
* NewEnv の実行
2. CEL式のパースとチェック
* Compile の実行
* Program の実行
3. 評価
* Eval の実行

“`NewEnv“` で使用する変数や追加の型を定義し、CEL式を “`Compile“` と “`Prog

元記事を表示

ざっくりgoroutine

# Goroutineの説明

## はじめに
Goroutineは、Go言語における軽量な並行処理の単位です。Goroutineを使用することで、効率的に並行処理を実装することができます。この記事では、Goroutineの基本的な概念、使い方、利点、注意点について説明します。

## 目次
1. [Goroutineとは](#goroutineとは)
2. [Goroutineの使い方](#goroutineの使い方)
3. [Goroutineの利点](#goroutineの利点)
4. [Goroutineの注意点](#goroutineの注意点)
5. [まとめ](#まとめ)

## Goroutineとは
Goroutineは、Go言語における並行処理のための軽量なスレッドのようなものです。Goroutineは非常に軽量であり、数千から数百万のGoroutineを同時に実行することができます。Goroutineは、Goランタイムによって管理され、必要に応じてスケジューリングされます。

## Goroutineの使い方
Goroutineを使用するには、関数呼び出しの前に `

元記事を表示

【Go言語】モックを利用したテスト

# はじめに

Goのモックの仕方を学ぶために、以下2つの方法を試していきたいと思います。

* [ライブラリを使わないモック](#ライブラリを使わないモック)
* [gomockを使用したモック](#gomock)

# テスト対象

今回は、以下の**foo.go**の`Fly()`のテストを実装していきたいと思います。

“`foo.go
type FourDimensionalPocket interface {
GetTakecopter() (string, error)
GetDokodemodoa() (string, error)
}

type Doraemon struct {
}

func (d Doraemon) GetTakecopter() (string, error) {
return “タケコプター🚁”, nil
}

func (d Doraemon) GetDokodemodoa() (string, error) {
return “どこでもドア🚪”, nil
}

func NewDoraemon() Doraemon {
re

元記事を表示

GoのCobraを使ってCLIを作ってみた

## はじめに
[前回](https://qiita.com/engineer_tacky/items/bbb2d740a6dc0da3a5ab)、flagパッケージを使ってCLIを作ってみたので、今回はCobraライブラリを使用してCLIを作ってみました。

## コード
ルートのコマンドとして、toolkitという名前のコマンドを作成しています。
そのサブコマンドとして、countとlinesを作りました。
Useフィールドにコマンド名、Runフィールドに実行する関数を登録します。
そして、それぞれFlags().StringP()で引数を定義します。
定義できたら、最後にAddCommand()で登録します。

“`main.go
package main

import (
“bufio”
“fmt”
“os”
“strings”

“github.com/spf13/cobra”
)

func main() {
var rootCmd = &cobra.Command{Use: “toolkit”}

var countCmd = &cobra.Comman

元記事を表示

Goでコマンドラインツールを作ってみた

## はじめに
コマンドラインツールを作るのは難しそうなイメージがありましたが、案外簡単に作れてしまいました。

## コード
“`main.go
package main

import (
“bufio”
“flag”
“fmt”
“os”
“strings”
)

func main() {
// コマンドライン引数の定義
filename := flag.String(“f”, “”, “検索対象のファイル名”)
word := flag.String(“w”, “”, “検索する単語”)
flag.Parse()

// 引数のバリデーション
if *filename == “” || *word == “” {
fmt.Println(“使用方法: -f <ファイル名> -w <検索単語>“)
flag.PrintDefaults()
os.Exit(1)
}

// ファイルを開く
file, err := os.Open(*filename)
if err != nil {
fmt.Printf(“ファイルを開けませんでし

元記事を表示

Goのジェネリクスを試してみた

## はじめに
Goのジェネリクスがよく理解できていなかったので、調べてみました。

## ジェネリクス導入前

int型、float64型のそれぞれで同じ処理をする関数を定義しています。
型が異なるので、両者を一緒に計算したり、戻り値で返したりすることができません。

“`go
package main

import “fmt”

// intスライスの合計を計算する関数
func sumIntSlice(slice []int) int {
sum := 0
for _, v := range slice {
sum += v
}
return sum
}

// float64スライスの合計を計算する関数
func sumFloat64Slice(slice []float64) float64 {
sum := 0.0
for _, v := range slice {
sum += v
}
return sum
}

func main() {
intSlice := []int{1, 2, 3, 4, 5}
floatSlice := []f

元記事を表示

Golangのポインタを理解したいと思った

# Go言語でのポインタの使用方法

## ポインタとは?
ポインタは、メモリ上の特定の位置を指し示す変数です。Go言語では、ポインタを使用することで、変数の値を直接操作したり、関数間でデータを効率的に渡すことができます。

## ポインタの基本
ポインタは、変数のアドレスを格納します。Go言語では、`*` 演算子を使用してポインタを宣言し、`&` 演算子を使用して変数のアドレスを取得します。

### ポインタの宣言と使用例
以下に、ポインタの基本的な使用例を示します。

“`go:例
package main

import “fmt”

func main() {
var x int = 10
var p *int = &x // x のアドレスを p に格納
fmt.Println(“x:”, x) // x: 10
fmt.Println(“p:”, p) // p: 0xc0000140a0 (メモリアドレス)
fmt.Println(“*p:”, *p) // *p: 10 (ポインタ p が指す値)
*p = 20 //

元記事を表示

GitHub Actions で Go の静的解析実行

CI の一環として、GitHub のデフォルトブランチに PR を作成した時と、マージをした時に静的解析を行う GitHub Actions を作成します。
※本記事は[GitHub Actions で Go のテスト実行](https://qiita.com/yoshihiro-kato/items/2a3725e2b8cc1682a288)の続編です

### ファイル構成
“`
.github
  ├─ actions
  │ └─ go-ut
  | └─ action.yml
  │ └─ static-check
  | └─ action.yml
  └─ workflows
  └─ ci.yml
json
  ├─ go.mod
  ├─ go.sum
  ├─ pretty_print.go
  └─ pretty_print_test.go
.gitignore
“`
UT も GitHub Actions から行っているため、静的解析の実行は action.yml に記載しています。

### Action
“`.g

元記事を表示

Goで再帰関数を作ってみる

## コード

フィボナッチ数列を計算する

“`go
package main

import (
“fmt”
)

func fibonacci(n int) int {
if n <= 1 { return n } return fibonacci(n-1) + fibonacci(n-2) } func main() { n := 10 fmt.Printf("fibonacci(%d) = %d\n", n, fibonacci(n)) } ``` ## 動かしてみる ```zsh go run main.go fibonacci(10) = 55 ``` ## コード 階乗を計算する ```go package main import ( "fmt" ) func factorial(n int) int { if n <= 1 { return 1 } return n * factorial(n-1) } func main() { n := 10 fmt.Printf("factoria

元記事を表示

Goでメール送信をやってみる

## コード

“`go
package main

import (
“fmt”
“net/smtp”
)

func main() {
// SMTPサーバーの設定
smtpHost := “smtp.gmail.com”
smtpPort := “587”
smtpUser := “ここに自分のGmailアカウント名@gmail.com”
smtpPass := “ここにSMTP送信用パスワード”

// 送信者と受信者のメールアドレス
from := “ここに自分のGmailアカウント名@gmail.com”
to := “ここに自分のGmailアカウント名@gmail.com”

// メールの件名と本文
subject := “【TEST】件名が入ります”
body := “本文です。”

// メールのメッセージ
message := []byte(“To: ” + to + “\n” + “Subject: ” + subject + “\n\n” + body)

// SMTP認証情報
auth := smtp.PlainAuth

元記事を表示

Goでディレクトリ操作をしてみる

## ディレクトリ作成
“`go
package main

import (
“fmt”
“os”
)

func main() {
dirName := “testDir”

err := os.Mkdir(dirName, 0755)
if err != nil {
fmt.Println(“Error creating directory:”, err)
return
}

fmt.Println(“Directory created successfully:”, dirName)
}
“`

## ディレクトリ作成(再帰)
“`go
package main

import (
“fmt”
“os”
)

func main() {
dirName := “dir1/dir2/dir3”

err := os.MkdirAll(dirName, 0755)
if err != nil {
fmt.Println(“Error creating directories:”, err)
return
}

fmt.Println

元記事を表示

OTHERカテゴリの最新記事