20200920のGoに関する記事は5件です。

Golang チュートリアル その3

概要

「処理が速い」「並行処理」が得意ということから、
今後大規模webサービスなどで重宝されると思いましたので、
学習していきたいと思います。

今回は、ポインタなどを見ていきたいと思います。

参考サイト

以下を実施してみました。

Welcome to a tour of Go

環境

GoogleChrome
※ブラウザ操作だけで学習できるため、 エディタを用意する必要がありません。
※私は、ローカルにCentOS8環境を用意して、チュートリアルを行います。
※Goインストール手順です。よろしければ、ご活用ください。
CentOS8へのGo言語インストール手順

ポインタ

ポインタは値のメモリアドレスを指します。

pointers.go
package main

import "fmt"

func main() {
    i, j := 42, 2701

    //iのメモリアドレスを取得
    p := &i
    //「*」をつけることをポインタで取得した変数の値を出力
    fmt.Println(*p)
    //出力している値を上書き
    *p = 21
    //上書きしたため、iの値が変更されている
    fmt.Println(i)

    //jのメモリアドレスを取得
    p = &j
    //「*」をつけることをポインタで取得した変数の値を出力
    fmt.Println(*p)
    //出力している値を上書き
    *p = *p / 37
    //上書きしたため、jの値が変更されている
    fmt.Println(j)
}

//実行
go run pointers.go

//実行結果
42
21
2701
73

Structs

struct (構造体)は、フィールド( field )の集まりです。

structs.go
package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    fmt.Println(Vertex{1, 2})
}

//実行
go run structs.go

//実行結果
{1 2}
  • Struct Fields

structのフィールドは、ドット( . )を用いてアクセスする。

struct-fields.go
package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    //Xフィールドへアクセスし、代入
    v.X = 4
    //代入した値が反映されている
    fmt.Println(v.X)
}

//実行
go run struct-fields.go

//実行結果
4
  • Pointers to structs

structのフィールドは、structのポインタを通してアクセスすることもできます。

フィールドXを持つstructのポインタ p がある場合、フィールド X にアクセスするには (*p).X のように書くことができます。
しかし、この表記法は大変面倒ですので、Goでは代わりに p.X と書くこともできます。

struct-pointters.go
package main

import "fmt"

type Vertex struct {
        X int
        Y int
}

func main() {
        v := Vertex{1, 2}
        //structsをポインタに代入
        p := &v
        //structsのXフィールドに値を代入
        p.X = 1e9
        fmt.Println(v)
}

structリテラル

structリテラルは、フィールドの値を代入することで新しいstructの初期値の割り当てを行っている。

Name: 構文を使って、フィールドの一部だけを列挙することができます
(この方法でのフィールドの指定順序は関係ありません)。
※例: X: 1 として X だけを初期化など

& を頭に付けると、新しく割り当てられたstructへのポインタを戻します。

struct-literals.go
package main

import "fmt"

type Vertex struct {
        X, Y int
}

var (
        //値を代入することで新しいstructの初期値の割り当てを行う
        v1 = Vertex{1, 2}
        //Xだけ初期値割り当てを行う
        v2 = Vertex{X: 1}
        //初期化
        v3 = Vertex{}
        //&を頭に付けると、新しく割り当てられたstructへのポインタを戻す
        p  = &Vertex{1, 2}
)

func main() {
        fmt.Println(v1, p, v2, v3)
}

//実行
go run struct-literals.go

//実行結果
{1 2} &{1 2} {1 0} {0 0}

配列(Arrays)

[n]T型で表す。
T型の配列にn個まで変数を入れられるという意味になります。

array.go
package main

import "fmt"

func main() {
    var a [2]string
    a[0] = "Hello"
    a[1] = "World"
    fmt.Println(a[0], a[1])
    fmt.Println(a)

    primes := [6]int{2, 3, 5, 7, 11, 13}
    fmt.Println(primes)
}

//実行
go run array.go

//実行結果
Hello World
[Hello World]
[2 3 5 7 11 13]

スライス(Slices)

スライスは可変長です。
より柔軟な配列と見なすこともできます。
実際には、スライスは配列よりもより一般的とのことです。

[]T型と表す。
T型のスライスという意味になります。

コロンで区切られた二つのインデックス low と high の
境界を指定することによってスライスが形成されます

例:a[low : high]

slices.go
package main

import "fmt"

func main(){
        primes := [6]int{2, 3, 5, 7, 11, 13}

        //1番目の値から4番目の値の間を取得
        //1番目は含む・4番目は含まない
        var s []int = primes[1:4]
        fmt.Println(s)
}

//実行
go run slices.go

//実行結果
[3 5 7]
  • スライスは配列への参照のようなもの

スライスはどんなデータも格納しておらず、
単に元の配列の部分列を指し示しています。

スライスの要素を変更すると、
その元となる配列の対応する要素が変更されます。

同じ元となる配列を共有している他のスライスは、
それらの変更が反映されます。

slice-pointers.go
package main

import "fmt"

func main(){
        names := [4]string{
                "John",
                "Paul",
                "George",
                "Ringo",
        }
        //配列を確認
        fmt.Println(names)

        //配列の中身をスライスに格納
        a := names[0:2]
        b := names[1:3]
        //格納されていることを確認
        fmt.Println(a, b)

        //スライスの中身を変更
        b[0] = "XXX"
        //変更した内容が配列にも反映されているか確認
        fmt.Println(a, b)
        fmt.Println(names)
}

//実行
go run slice-pointers.go

//実行結果
[John Paul George Ringo]
[John Paul] [Paul George]
[John XXX] [XXX George]
[John XXX George Ringo]
  • スライスのリテラル(初期値割り振りの認識)

・配列リテラル
[3]bool{true, true, false}

・スライスリテラル
[]bool{true, true, false}

slice-literals.go
package main

import "fmt"

func main() {
    q := []int{2, 3, 5, 7, 11, 13}
    fmt.Println(q)

    r := []bool{true, false, true, true, false, true}
    fmt.Println(r)

    s := []struct {
        i int
        b bool
    }{
        {2, true},
        {3, false},
        {5, true},
        {7, true},
        {11, false},
        {13, true},
    }
    fmt.Println(s)
}

//実行
go run slice-literals.go

//実行結果
[2 3 5 7 11 13]
[true false true true false true]
[{2 true} {3 false} {5 true} {7 true} {11 false} {13 true}]
  • スライスの長さ( length )と容量( capacity )

スライスの長さ:スライスに含まれる要素の数。
スライスの容量:スライスの最初の要素から数えて、元となる配列の要素数。

slice-len-cap.go
package main

import "fmt"

func main(){
        s := []int{2, 3, 5, 7, 11, 13}
        printSlice(s)

        //スライスの長さを0にする
        s = s[:0]
        printSlice(s)

        //スライスの長さを伸ばす
        s = s[:4]
        printSlice(s)

        //スライスの値を削除
        s = s[2:]
        printSlice(s)
}

func printSlice( s []int){
        fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

//実行
go run slice-len-cap.go

//実行結果
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
  • スライスのゼロ値

スライスのゼロ値は nil です。
nil スライスは 0 の長さと容量を持っており、
何の元となる配列も持っていません。
※宣言するだけの時に使用する認識

nil-slices.go
package main

import "fmt"

func main() {
    var s []int
    fmt.Println(s, len(s), cap(s))
    if s == nil {
        fmt.Println("nil!")
    }
}

//実行
go run nil-slices.go

//実行結果
[] 0 0
nil!
  • スライスは、組み込みのmake関数を使用して作成

動的サイズの配列を作成する方法です。
make関数はゼロ化された配列を割り当て、その配列を指すスライスを返す。
※make関数が対応する型はslice,map,chanelのみ
※上記は、Goのnew関数とmake関数の違いを解説する参照

making-slices.go
package main

import "fmt"

func main() {
    a := make([]int, 5)
    printSlice("a", a)

    b := make([]int, 0, 5)
    printSlice("b", b)

    c := b[:2]
    printSlice("c", c)

    d := c[2:5]
    printSlice("d", d)
}

func printSlice(s string, x []int) {
    fmt.Printf("%s len=%d cap=%d %v\n",
        s, len(x), cap(x), x)
}

//実行
go run making-slices.go

//実行結果
a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0]
d len=3 cap=3 [0 0 0]
  • Slices of slices

スライスは、他のスライスを含む任意の型を含むことができる。

slices-of-slices.go
package main

import (
    "fmt"
    "strings"
)

func main() {
    // Create a tic-tac-toe board.
    board := [][]string{
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
    }

    // The players take turns.
    board[0][0] = "X"
    board[2][2] = "O"
    board[1][2] = "X"
    board[1][0] = "O"
    board[0][2] = "X"

    for i := 0; i < len(board); i++ {
        fmt.Printf("%s\n", strings.Join(board[i], " "))
    }
}

//実行
go run slices-of-slices.go

//実行結果
X _ X
O _ X
_ _ O
  • スライスへ新しい要素を追加

Goの組み込みの append を使います。

append.go
package main

import "fmt"

func main() {
        var s []int
        printSlice(s)

        s = append(s, 0)
        printSlice(s)

        s = append(s, 1)
        printSlice(s)

        s = append(s, 2, 3, 4)
        printSlice(s)
}

func printSlice(s []int) {
        fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

//実行
go run append.go

//実行結果
len=0 cap=0 []
len=1 cap=1 [0]
len=2 cap=2 [0 1]
len=5 cap=6 [0 1 2 3 4]

Range

for ループに利用する range は、スライスや、マップ( map )を
ひとつずつ反復処理するために使います。

スライスをrangeで繰り返す場合、rangeは反復毎に2つの変数を返します。
1つ目の変数はインデックス( index )で、2つ目はインデックスの場所の要素のコピーです。

range.go
package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main(){
        for i, v := range pow{
                fmt.Printf("2**%d = %d\n", i,v)
        }
}

//実行
go run range.go

//実行結果
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128
  • Range continued

インデックスや値は、 " _ "(アンダーバー) へ代入することで捨てることができます。

※ソースは一部変更しております。

range-continued.go
package main

import "fmt"

func main(){
        pow := make([]int, 10)

        for i := range pow {
                pow[i] = 1 << uint(i)
                fmt.Println(pow)
        }

        for _, value := range pow{
                fmt.Printf("%d\n", value)
        }
}

//実行
go run range-continued.go

//実行結果
[1 0 0 0 0 0 0 0 0 0]
[1 2 0 0 0 0 0 0 0 0]
[1 2 4 0 0 0 0 0 0 0]
[1 2 4 8 0 0 0 0 0 0]
[1 2 4 8 16 0 0 0 0 0]
[1 2 4 8 16 32 0 0 0 0]
[1 2 4 8 16 32 64 0 0 0]
[1 2 4 8 16 32 64 128 0 0]
[1 2 4 8 16 32 64 128 256 0]
[1 2 4 8 16 32 64 128 256 512]
1
2
4
8
16
32
64
128
256
512

Maps

map はキーと値とを関連付けます。

マップのゼロ値は nil です。 nil マップはキーを持っておらず、
またキーを追加することもできません。
make 関数は指定された型のマップを初期化して、使用可能な状態で返します。

maps.go
package main

import "fmt"

type Vertex struct{
        Lat, Long float64
}

var m map[string]Vertex

func main(){
        m = make(map[string]Vertex)
        m["Bell Labs"]  = Vertex{
                40.68433, -74.39967,
        }
        fmt.Println(m["Bell Labs"])
}

//実行
go run maps.go

//実行結果
{40.68433 -74.39967}
  • Map literals

mapリテラルは、structリテラルに似ていますが、 キー ( key )が必要です。

map-literals.go
package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m = map[string]Vertex{
    "Bell Labs": Vertex{
        40.68433, -74.39967,
    },
    "Google": Vertex{
        37.42202, -122.08408,
    },
}

func main() {
    fmt.Println(m)
}

//実行
go run map-literals.go

//実行結果
map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]
  • Map literals continued

もし、mapに渡すトップレベルの型が単純な型名である場合は、
リテラルの要素から推定できますので、その型名を省略することができます。

map-literals-continued.go
package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m = map[string]Vertex{
    "Bell Labs": {40.68433, -74.39967},
    "Google":    {37.42202, -122.08408},
}

func main() {
    fmt.Println(m)
}

//実行
go run map-literals-continued.go

//実行結果
map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]
  • Mapsの操作

■m へ要素(elem)の挿入や更新の場合
m[key] = elem

■要素の取得:
elem = m[key]

■要素の削除:
delete(m, key)

■キーに対する要素が存在するかどうか
※2つの目の値で確認します

elem, ok = m[key]
※もし、 m に key があれば、変数 ok は true となり、
 存在しなければ、 ok は false となります。

mutating-maps.go
package main

import "fmt"

func main() {
    m := make(map[string]int)

    //挿入
    m["Answer"] = 42
    fmt.Println("The value:", m["Answer"])

    //更新
    m["Answer"] = 48
    fmt.Println("The value:", m["Answer"])

    //削除
    delete(m, "Answer")
    fmt.Println("The value:", m["Answer"])

    //検索
    v, ok := m["Answer"]
    fmt.Println("The value:", v, "Present?", ok)
}

//実行
go run matating-maps.go

//実行結果
The value: 42
The value: 48
The value: 0
The value: 0 Present? false

関数(Function values)

関数も変数です。他の変数のように関数を渡すことができます。
関数値( function value )は、関数の引数に取ることもできますし、戻り値としても利用できます。

function-values.go
package main

import (
    "fmt"
    "math"
)

func compute(fn func(float64, float64) float64) float64 {
    return fn(3, 4)
}

func main() {
    hypot := func(x, y float64) float64 {
        return math.Sqrt(x*x + y*y)
    }
    fmt.Println(hypot(5, 12))

    fmt.Println(compute(hypot))
    fmt.Println(compute(math.Pow))
}

//実行
go run function-values.go

//実行結果
13
5
81
  • Function closures

Goの関数は クロージャ( closure ) です。
クロージャは、それ自身の外部から変数を参照する関数値です。
この関数は、参照された変数へアクセスして変えることができ、
その意味では、その関数は変数へ"バインド"( bind )されています。

function-closures.go
package main

import "fmt"

func adder() func(int) int {
    sum := 0
    return func(x int) int {
        sum += x
        return sum
    }
}

func main() {
    pos, neg := adder(), adder()
    for i := 0; i < 10; i++ {
        fmt.Println(
            pos(i),
            neg(-2*i),
        )
    }
}

//実行
go run function-closures.go

//実行結果
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90

まとめ

次回はメソッドなどを見ていきたいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Golang】Go言語のmapについて解説

今日はGoのmapについて学習したのでこちらにアウトプットします!!

mapとは?

rubyでいうと、ハッシュ(連想配列)に該当するものです。
キーと値がセットになっているものです。

とりあえず色々書いてみる

package main

import "fmt"

func main() {
    m := map[string]int{"udon": 500, "ra-men": 800, "soba": 700}
    fmt.Println(m) // => map[ra-men:800 soba:700 udon:500]

    //値へのアクセス
    fmt.Println(m["ra-men"]) // => 800

    //値の更新
    m["udon"] = 450
    fmt.Println(m) // => map[ra-men:800 soba:700 udon:450]
    //値の追加
    m["new"] = 1000
    fmt.Println(m) // => map[new:1000 ra-men:800 soba:700 udon:450]

    //値が入っているか確かめることができる
    v, ok := m["soba"]
    fmt.Println(v, ok) // => 700 true

    v2, ok2 := m["so-men"]
    fmt.Println(v2, ok2) // => 0 false

    //メモリ上に空のマップを作ってから代入することもできる
    m2 := make(map[string]int)
    m2["tya-han"] = 400
    fmt.Println(m2) // => map[tya-han:400]

    //こちらは宣言はしているがメモリ上に入れるマップがないのでエラーになる
    var m3 map[string]int
    m3["tya-han"] = 400
    fmt.Println(m3) // => ERROR

    //↑のようにvarで宣言した場合はmapのときはnilが入っている(スライスも同様)
    var m3 map[string]int
    if m3 == nil {
        fmt.Println("Nil!") // => Nil!
    }
        //スライスの場合もnil
    var s []int
    if s == nil {
        fmt.Println("Nil!") // => Nil!
    }
}

参考文献

こちらも併せて読んでいただけるとより理解が深まると思います!
Go言語: いろいろなマップの作り方まとめ
逆引きGolang (マップ)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Goの初心者がechoを使って、"Hello World"をブラウザに表示するまで

目次

  1. goenvをインストール
  2. goをインストール
  3. go moduleを初期化
  4. "Hello World" を表示させるコードを書く
  5. echoをインストール
  6. hello.goを実行し、ブラウザにアクセス

1. goenvをインストール

goのバージョンを管理するツール
rubyでいうところのrbenv

$ brew install goenv

パスを通す

//現在のシェルを確認
$ echo $SHELL 
> /bin/bash

- bashの場合 .bash_profileにパスを設定
- zshの場合 .zshrcにパスを設定

$ cd ~  // ホームディレクトリに移動

$ ls -a //カレントディレクトリのファイル等を表示

// 私の場合、 シェルがbashなので、 .bash_profileがなければ作成する
$ touch .bash_profile
$ touch .zshrc // 現在のシェルがzshで、 .zshrcファイルがなければこちらのコマンド

//ファイルにパスを追加する

$ vim .bash_profile

//以下を最後の行に追加
export PATH="$HOME/.goenv/bin:$PATH"
eval "$(goenv init -)"

//設定の変更を反映させる
$ source ~/.bash_profile

2. Goをインストール

// インストールできるバージョンを確認
$ goenv install -l 

// バージョンを指定してインストール
$ goenv install 1.13.1

// インストールできたか確認
$ goenv versions    // 現在使用可能なバージョンが表示される

// インストールしたgoのバージョンを適応する
$ goenv global 1.13.1   //全てのディレクトリで1.13.1バージョンが使える
$ goenv rehash

$ go version  // 現在設定されているバージョンを確

3. go moduleを初期化する

$ go mod init app

// ディレクトリ構造
go
├── go.mod    //新たに作成される
└── main.go
go.mod
//このファイルはgit mod init コマンドで自動に生成される

module app

go 1.13

require (
    github.com/labstack/echo v3.3.10+incompatible
    github.com/labstack/echo/v4 v4.1.17 // indirect
)

4. "Hello World" を表示させるコードを書く

ディレクトリとファイルを作成

$ mkdir go
$ cd go
$ touch main.go

ファイルの中身を書く

main.go
package main

import (
    "net/http"
    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello World")
    })
    e.Logger.Fatal(e.Start(":1323"))
}

5. Echoをインストール

$ go get github.com/labstack/echo/v4

6. main.goを実行

$ go run main.go
go: finding golang.org/x/crypto latest
go: downloading github.com/mattn/go-colorable v0.1.2
go: downloading github.com/mattn/go-isatty v0.0.9
go: downloading github.com/valyala/fasttemplate v1.0.1
...
...
...
   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:1323

// 必要なモジュールがダウンロードされていき、go.sumに依存しているモジュールのファイルツリーのハッシュ値が記録される

//ディレクトリ構造
go
├── go.mod
├── go.sum  // 追加される
├── main  // 追加される
└── main.go

go.sumの中身

go.sum
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/echo/v4 v4.1.17 h1:PQIBaRplyRy3OjwILGkPg89JRtH2x5bssi59G2EL3fo=
github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ=
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
...
...
...

http://localhost:1323/にアクセスすると"Hello World"と表示される

もしも、go run main.goで以下のエラーが出てしまったら

すでにポートが使われているプロセスがあるので、そのプロセスを終了させる

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
{"time":"2020-09-21T04:05:07.089506+09:00","level":"FATAL","prefix":"echo","file":"hello.go","line":"13","message":"listen tcp :1323: bind: address already in use"}
exit status 1

// psコマンドで実行中のプロセスを確認
$ ps
  526 ttys000    0:00.29 -bash
 2974 ttys001    0:00.09 /bin/bash -l
 3636 ttys001    0:00.78 go run main.go

//同じポート番号を使っているであろうプロセスを削除
$ kill -9 3636

注意点

[GO言語] Depはもう古い GoModulesへ移行しよう

Goの環境設定を調べていると"GOPATHを設定する"記事を結構目にしますが、GOPATHを設定すると色々とエラーが出たのと、もう古いらしいのでGOPATHは設定していません。

参考

Golangをgoenvを使ってインストールしてみた
【zsh, bash】macでPATHを通す方法 - not found と出てしまったら
よく使う Vim のコマンドまとめ
GolangとEchoでお手軽にAPIサーバを立てる
Go Modules
Address already in use の対処法

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Sapper × Go(echo) × Dockerの開発環境構築

はじめに

フロント:Svelte.js(Sapper),API:Go(echo)でアプリを作ってみたかったので
Dockerを使って構築した。

どこまでやるか

Sapper,echoをローカルホストで接続できるところまで

初期のディレクトリ構造

今回の環境構築にあたり、「Vue.js + Go言語 + Docker」で作る!画像アップロード機能実装ハンズオン
を参考にさせていただきました。

シンプルでわかりやすい。

.
├── docker-compose.yml
└── server

Sapperの開発環境構築

npx degit "sveltejs/sapper-template#rollup" client

cd client
npm install
touch Dockerfile_develop

Dockerfileですが、自分の場合production用のDockerfileも用意したいため、名前をDockerfile_developにしてます。
特に分ける必要がなかったり、マルチステージビルドでおさまりそうであれば一個にしてしていただいて構いません。

Dockerfile

FROM mhart/alpine-node:12

WORKDIR /app
COPY package.json package-lock.json ./

RUN npm ci

ENV HOST=0.0.0.0
EXPOSE 3000

docker-compose.yml

version: '3.8'

services:
  client:
    env_file: .env
    build: 
      context: ./client
      dockerfile: Dockerfile_${DOCKER_ENV} # この行はいらなければ削除
    ports:
      - 3000:3000
    tty: true
    volumes:
      - ./client:/app
    command: npm run dev

※環境変数がある場合

touch .env
vim .env
DOCKER_ENV=develop

この段階でSapperが起動するかみてみましょう

docker-compose up --build

Go(echo)の開発環境構築

cd server
touch Dockerfile
touch main.go

Dockerfile

FROM golang:1.15.2-alpine


WORKDIR /go/src/api
ADD .  /go/src/api
ENV GO111MODULE=off

RUN apk update && apk add curl git

main.go

package main

import (
  "net/http"
  "github.com/labstack/echo"
)

func main() {
  e := echo.New()
  e.GET("/", func(c echo.Context) error {
    return c.String(http.StatusOK, "Hello, World")
  })
  e.Logger.Fatal(e.Start(":8080"))
}

docker-compose.yml

version: '3.8'
...
  server:
    build: ./server
    ports:
      - 8080:8080
    tty: true
    volumes:
      - ./server:/api

echoのローカルサーバーを立ち上げます。

docker-compose up --build
docker-compose exec server /bin/ash
go get github.com/labstack/echo
go run main.go

これでlocalhost:8080にアクセスできれば完了です。

おわりに

次はGorm, MySQLを入れるところまでやりたい

参考資料

「Vue.js + Go言語 + Docker」で作る!画像アップロード機能実装ハンズオン
svelteの開発環境の作り方
Hello World Recipe

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AtCoder Beginner Contest 179のメモ

前置き

Atcoderをやってみたので、自分用のメモです。
あとから加筆・修正する予定です。

問題

https://atcoder.jp/contests/abc179

A

Q_A.go
package main

import (
    "fmt"
)

func main() {
    var s string
    fmt.Scan(&s)

    if s[len(s)-1:] == "s"{
        s = s + "es"
    } else {
        s = s + "s"
    }

    fmt.Printf("%s\n", s)
}

B

Q_B.go
package main

import (
    "fmt"
)

func main() {
    var n int
    fmt.Scanf("%d", &n)

    D := make([][]int, n)
    for i := 0; i < n; i++ {
        D[i] = make([]int, 2)
        fmt.Scanf("%d %d", &D[i][0], &D[i][1])
    }

    var count int = 0
    var result bool = false

    for i := 0; i < n ; i ++{
        if D[i][0] == D[i][1]{
            count = count+1 
        } else {
            count = 0
        }

        if count == 3{
            result = true
            break
        }
    }

    var msg string

    if result {
        msg = "Yes"
    } else {
        msg = "No"
    }

    fmt.Printf("%s\n", msg)
}

C

Q_C.go
package main

import (
    "fmt"
)

func main() {
    var n int
    fmt.Scanf("%d", &n)

    var count int = 0
    for a:=1; a<n ; a++{
        var b_max = int((n-1) / a)
        for b:=1; b<=b_max; b++{
            if a * b < n{
                count = count+1
            }
        }
    }

    fmt.Printf("%d\n", count)
}

D

Q_D.go
package main

import (
    "fmt"
)

func main() {
    var n, k int
    fmt.Scanf("%d %d", &n, &k)

    var s[] int
    var flag bool = true

    for i := 0; i < k; i++ {
        var l, r int 
        fmt.Scanf("%d %d", &l, &r)
        for ; l<=r; l++{
            for i:=0; i<len(s); i++{
                if l == s[i]{
                    flag = false
                    break
                }
            }
            if flag{
                s = append(s, l)
            }
        }
    }

    var f[200001] int
    f[0] = 1

    for i := 1; i<n; i++{
        var count int = 0
        for j:=0; j<len(s); j++{
            if s[j] <= i{
                count += f[i-s[j]]
            }
        }
        f[i] = count
    }

    fmt.Printf("%d\n", f[n-1]%998244353)
}

E

覚えてたら後で書きます。

F

覚えてたら後で書きます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む