Golang : 動的なjsonを扱う方法

はじめに

JavaScriptphpなどの型のゆるい言語を使い慣れると、Goのオブジェクトの扱い方に戸惑います。たまにGoを使うのですが、そのたびにはまるので、備忘録として当記事を残します。

サンプルコード

  • 扱うjson
{
    "count": 2,
    "hits": [
        {
            "code": "123-4567",
            "address": "XXX県YYY市ZZZ町"
        },
        {
            "code": "987-6543",
            "address": "aaa県bbb市ccc町"
        }
    ]
}
  • json → interface{}
package main

import (
    "encoding/json"
    "log"
)

func main() {
    var jsonBlob = []byte(`{
        "count": 2,
        "hits": [{"code": "123-4567", "address": "XXX県YYY市ZZZ町"}, {"code":"987-6543", "address":"aaa県bbb市ccc町"}]
    }`)
    var data interface{}
    err := json.Unmarshal(jsonBlob, &data)
    if err != nil {
        log.Panic(err)
    }
    log.Printf("%#v", data)
    //→ map[string]interface {}{"count":2, "hits":[]interface {}{map[string]interface {}{"address":"XXX県YYY市ZZZ町", "code":"123-4567"}, map[string]interface {}{"address":"aaa県bbb市ccc町", "code":"987-6543"}}}

    log.Println(data.(map[string]interface{})["count"].(float64))
    log.Println(data.(map[string]interface{})["hits"].([]interface{})[0].(map[string]interface{})["address"].(string))
    log.Println(data.(map[string]interface{})["hits"].([]interface{})[1].(map[string]interface{})["address"].(string))
    // → 2
    //    XXX県YYY市ZZZ町
    //    aaa県bbb市ccc町
}
  • map → json
package main

import (
    "encoding/json"
    "log"
)

func main() {
    var hits []map[string]interface{}
    hit := map[string]interface{}{"code": "123-4567", "address": "XXX県YYY市ZZZ町"}
    hits = append(hits, hit)
    hit = map[string]interface{}{"code":"987-6543", "address":"aaa県bbb市ccc町"}
    hits = append(hits, hit)

    var data map[string]interface{}
    count := 2
    data = map[string]interface{}{"count": count, "hits": hits}

    log.Printf("%#v", data)
    // → map[string]interface {}{"count":2, "hits":[]map[string]interface {}{map[string]interface {}{"address":"XXX県YYY市ZZZ町", "code":"123-4567"}, map[string]interface {}{"address":"aaa県bbb市ccc町", "code":"987-6543"}}}
    bytes, err := json.Marshal(&data)
    if err != nil {
        log.Panic(err)
    }
    log.Println(string(bytes))
    // → {"count":2,"hits":[{"address":"XXX県YYY市ZZZ町","code":"123-4567"},{"address":"aaa県bbb市ccc町","code":"987-6543"}]}
}

参考

https://www.kaoriya.net/blog/2016/06/25/

ワンライナーでWebサーバ

はじめに

ちょっとしたプログラムの動作確認で、Webサーバを起動したいときってありますよね。
そんな時、私はワンライナーで実行できるWebサーバを利用しています。


  • 環境:Windows10
  • 公開したいディレクトリに移動し、以下のコマンドを実行します。

Node.js

npx http-server -p 8080

参考資料
https://www.npmjs.com/package/http-serve

Golang

  • goexecインストール

    go get -u github.com/shurcooL/goexec
  • webサーバ実行

    goexec http.ListenAndServe(\":8080\",http.FileServer(http.Dir(\".\")))

参考資料
https://github.com/golang/go/wiki/WebAssembly

Python 3.x

python -m http.server 8081

参考資料
https://docs.python.org/ja/3/library/http.server.html

PHP

php -S localhost:8081

参考資料
https://www.php.net/manual/ja/features.commandline.webserver.php

nginxの配下でnodejsやgolangを動かす方法

nodejsやgolangは自分自身がWebサーバの機能も持ち合わせています。

それはそれで便利なのですが、それらのプログラムがフロントに立ってしまうと複数のプログラムを実行する場合は、その分ポートを開ける必要があります。

また、それが外部に公開するサービスだとしたら、443以外のポートにリクエストを送らなければならない仕様となり、利用者も扱いにくいです。

そのため、フロントに別のWebサーバを立てる必要があるかと思います。

mainserver.com
mainserver.com
https://mainserver.com/gosample
→http/port:8081へ転送
https://mainserver.com/gosample…
https://mainserver.com/nodesample
→http/port:8082へ転送
https://mainserver.com/nodesample…
Viewer does not support full SVG 1.1

上記のような構成でのnginx最小限の設定は以下の通りです。

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name mainserver.com;

    location /gosample/ {
        proxy_pass http://127.0.0.1:8081/;
    }

    location /nodesample/ {
        proxy_pass http://127.0.0.1:8082/;
    }
}