http.HandleFunc と http.Handle の違い(原理はどーでもよくて)についての自分なりのまとめ
以下の記述は間違っているようですので、参照にしないで下さい(現在検証中)。
(昨日、ソフト外注会社の方に教えて貰いました)
Golangで、http.HandleFunc と http.Handleについて、ずっと混乱しつづけています。
というか、私は、使い方が分かればよくて、その理屈なんぞ1mmも興味がないので、コードを書きながら理解しています(結局、遅くなっているような気がしますが)。
1. http.Handle()は、index.htmlをベースとしたサーバを立てるもの
// main16.go 現在の居場所は、c:\Users\ebata\hirohakama\199A2\others
/*
.
├── main16.go
├── index.html (A)
└── chart # chartフォルダに静的ファイルがある
└── index.html (B)
*/
package main
import (
"net/http"
)
func main() {
// 静的ファイル配信.
// ディレクトリ名をURLパスに使う場合
// 例:http://localhost:8080/chart/で index.html (B) の方を表示
http.Handle("/chart/", http.FileServer(http.Dir("./")))
// 例:http://localhost:8080/で index.html (A) の方を表示
http.Handle("/", http.FileServer(http.Dir("./")))
// ディレクトリ名とURLパスを変える場合
// 例:http://localhost:8080/mysecret/sample1.txt
// http.Handle("/mysecret/", http.StripPrefix("/mysecret/", http.FileServer(http.Dir("./contents"))))
// 例:http://localhost:8080/で index.html (A) の方を表示
http.Handle("/", http.FileServer(http.Dir("./")))
// 8080ポートで起動
http.ListenAndServe(":8080", nil)
}
これで、main16.goが置いている場所が、基準点となります(それだけです)。
で、色々考えずに、基本は、
http.Handle("/", http.FileServer(http.Dir("./")))
としておきましょう(というか、これがデフォルトなら、記載すらしなくてもいい)
2. http.HandleFunc()は、ソースコードで書いたものをサーバとするもの
// main15.go 現在の場所はc:\Users\ebata\hirohakama\199A2\others
/*
.
└── main15.go
*/
package main
import (
"io"
"log"
"net/http"
)
func h1(w http.ResponseWriter, _ *http.Request) {
io.WriteString(w, "Hello from a HandleFunc #1!\n")
}
func h2(w http.ResponseWriter, _ *http.Request) {
io.WriteString(w, "Hello from a HandleFunc #2!\n")
}
func main() {
// http://localhost:8080/ で h1の内容を表示 (プログラムの内容を)
http.HandleFunc("/", h1)
// http://localhost:8080/endpoint で h2の内容を表示
http.HandleFunc("/endpoint", h2)
log.Fatal(http.ListenAndServe(":8080", nil))
}
3. http.Handle()1つとhttp.handleFunc()1つが混在しているものは、それぞれサーバが2つある、ということ
// main13.go
package main
import (
"fmt"
"log"
"math/rand"
"net/http"
"time"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{}
type GetLoc struct {
ID int `json:"id"`
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
TYPE string `json:"type"` // "PERSON","BUS","CONTROL
POPUP int `json:"popup"`
//Address string `json:"address"`
}
func echo3(w http.ResponseWriter, r *http.Request) {
upgrader.CheckOrigin = func(r *http.Request) bool { return true } // おまじない
conn2, err := upgrader.Upgrade(w, r, nil) //conn2でwebsocketを作成
if err != nil {
log.Println("websocket connection err:", err)
return
}
defer conn2.Close()
for {
gl2 := new(GetLoc)
gl2.ID = rand.Intn(20) // ここで乱数を発生されて、javascriptで受信させる
gl2.Lat = 181.0
gl2.Lng = 181.0
gl2.TYPE = "BUS"
gl2.POPUP = 101
err := conn2.WriteJSON(&gl2)
if err != nil {
log.Println("ReadJSON:", err)
break
}
fmt.Println("echo3:", gl2)
time.Sleep(time.Second * 1)
}
}
//var addr = flag.String("addr", "0.0.0.0:5000", "http service address") // テスト
func main() {
http.Handle("/chart/", http.FileServer(http.Dir("./")))
http.HandleFunc("/echo3", echo3)
//log.Println("server starting...", "http://localhost:8080")
//log.Fatal(http.ListenAndServe("localhost:8080", nil))
log.Fatal(http.ListenAndServe(":8080", nil))
}
index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test</title>
</head>
<script type="text/javascript" src="moment.js"></script>
<script type="text/javascript" src="Chart.js"></script>
<script type="text/javascript" src="chartjs-plugin-streaming.js"></script>
<script>
var ws;
// websocketのオープン(この段階で接続完了)
ws = new WebSocket('ws://localhost:8080/echo3') // ユーザ登録画面
ws.onopen = function (event) {
}
ws.onmessage = function (event) {
// 送られてきたデータを受信して、JSON形式に変更
var obj = JSON.parse(event.data);
console.log("obj:",obj);
console.log("obj.id:",obj.id);
aa = obj.id;
}
</script>
<body BGCOLOR="black" text="white" STYLE="overflow: hidden;">
<center>
<font size="5">Waking Time(min.) <br></font> <!--- 意味のない表示 -->
<font size="5"> 歩行時間(分)</font> <!--- 意味のない表示 -->
</center>
<canvas id="myChart" width="100" height="85"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
data: [], // 1つめ
borderColor: "rgba(255,0,0,1)",
backgroundColor: "rgba(0,0,0,0)",
lineTension: 0,
label: 'Time',
}]
},
options: {
scales: {
xAxes: [{
type: 'realtime',
realtime: {
duration: 30000, // 300000ミリ秒(5分)のデータを表示 (コメントアウトすると早く動く)
onRefresh: function(chart) {
chart.data.datasets.forEach(function(dataset) {
dataset.data.push({
x: Date.now(),
//y: (Math.floor(Math.random()*16)+30) //30-45の乱数(整数)
y: aa, // この"aa"が、送られてきたデータ
});
});
}
}
}],
yAxes: [{
ticks: {
max: 20,
min: 0
}
}]
}
}
});
</script>
</body>
</html>
この場合、
- /chart/index.htmlをベースとするサーバと、
- echo3()が作るサーバ
の2つがある、ということ。
実際のところ、echo3は、/chart/index.html のクライアント(データの送信元)でもあるんだけど、要求があれば、ポコポコ作り出される、という点ではサーバでもある、という形になっています。
―― という説明を、次に私が頭を抱えた時に、私が思い出せるのかが、不安です