Help us understand the problem. What is going on with this article?

AngularJSのhttp通信からのpostリクエストをgo側で取得

More than 1 year has passed since last update.

Goの勉強録

Goを本格的に勉強をし始めて割とモチベが保てているなと思います。PHPのWebソフトウェア開発と並行して勉強できているので生活にハリと艶が出てきているような気がします。(・∀・)
余談ですが、最近JSの他のフレームワークに魅了を感じますね、例えばVue.jsとかは綺麗なサイトができるのでAngularから浮気をしそうになります。(まだしていません。。)
しかし、Angular界隈を盛り上げていきたいためまだまだAngular頑張ります!
Go言語に関する過去記事は以下になります。

過去の記事

本題

さて、今回の本題のAngular側からhttp通信でPOSTリクエストをGo言語でそのデータをJSONで取得するというものをやっていきます。
これPHPなら一行でできるのですが。。
今回の実装のフローは
- テキストボックスとボタンのhtmlを作る
- AngularJSでテキストボックスの値を取得できるようにする。
- ボタンを押した際に実行されるリスナーを定義する。
- go 側でhttp通信で送られて来るデータと同じ形式の構造体を定義する。
- レスポンスのBodyをjson.NewDecoder(io Reader)でDecoderを作成する。
- 生成したdecoderからDecodeを行いgoで定義した構造体に格納
- その構造体を出力
フローはこんな感じですが 百聞は一見にしかず なのでコードを見ていきましょう。

ちなみに、ディレクトリの構造は以下のようになっています。

ディレクトリ
workspace/
  ├ HTML/
  │    ├ index.html
  │    ├ test.js
  │
  ├ POST/
  │    ├ post.go
  │
  ├ Host.go

ソースコード

まずは、表示側のindex.html

index.html
<html ng-app="test">
    <head>
        <title>post test</title>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js"></script>
        <script src="./test.js"></script>
    </head>
    <body ng-controller="test">
        <input type="text" ng-model="val">
        <input type="button" value="送信" ng-Click="test()">
    </body>
</html>

通信を送る側のtest.js

test.js
var test = angular.module("test",[])

test.controller("test",function($scope,$http){
    $scope.test = function(){
        send = {
            name: $scope.val
        }
        console.log(send);
        $http({
        method: 'POST',
        url: '../Host.go',
        contentType: 'application/JSON',
        data: send
      }).then(function DoneCallback(res){
          console.log("通信成功");
          console.log(res)
        },function failCallback(res){
            console.log("通信失敗");
        });
    }
})

Host.goはサーバを立てるスクリプトです。
リクエストはHost.goで受けていますが、処理はpost.goに投げています。

Host.go
package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
    "reflect"

    "./POST"
)

func main() {
        // リクエストがきた際の処理の定義
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        POST.Procreq(w, r)
    })
    dir, _ := os.Getwd()
    fmt.Println(reflect.TypeOf(dir))
    http.Handle("/posttest/", http.StripPrefix("/posttest/", http.FileServer(http.Dir(dir+"/HTML/"))))
    log.Fatal(http.ListenAndServe(":8080", nil))
}

実際に来るリクエストのデータの取得はこのpost.goで行なっています。

post.go
package POST

import (
    "encoding/json"
    "fmt"
    "net/http"
)

// リクエストのデータ構造と形式が同じ構造体を定義
type Test struct {
    Name string
    // for debug
    // Val  string
    // Ope   string
}

func Procreq(w http.ResponseWriter, r *http.Request) {
    // パース
    r.ParseForm()
    // インスタンスの生成
    var test = Test{}
    // postのリクエストを処理する
    //decoderの生成
    decoder := json.NewDecoder(r.Body)
    // testにリクエストデータを格納
    err := decoder.Decode(&test)
    if err != nil {
        panic(err)
    }
    fmt.Println("method : " + r.Method)
    fmt.Println("name : " + test.Name)
}

ソースコードはこんな感じです。

bash
go run Host.go

を叩くと、http://localhost:8080/posttest/にindex.htmlが出力されていてテキストボックスにtestを入力してボタンを押すとコンソール側は次のようなログを表示します

string
method : POST
name : test

このようにデータをJSON形式で受け取ることができているので、あとはこのデータを煮るなり焼くなりすればいいと思います。

まとめ

データを取得するのに手こずってしまいました。
teratailでも質問しましたが、試行錯誤で自己解決できました。(回答を送っていただいた方々ありがとうございました。)
phpと違う点は受け取り側がデータの構造体を定義しないといけないということで、初学者ながらgo言語のコンセプトである一貫性を持たせることなのかなと思いました。

参考

https://www.pebblewind.com/entry/2017/03/03/181956
https://teratail.com/questions/177365#reply-264307

lkeix_
情報系の学生です. Go言語 Docker TypeScript を勉強しています
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away