go言語のmap、sliceのコピー

mapのコピー

go言語でmapは参照型のため、コピーするとき注意が必要。
以下にコードを例示する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import "fmt"
func main() {
m1 := make(map[string]int)
m1["a"] = 1
m1["b"] = 2
m2 := m1 //同じものを参照する
m2["c"] = 3
fmt.Println(m1) //map[a:1 b:2 c:3]
fmt.Println(m2) //map[a:1 b:2 c:3]
}

完全に別のmapとしてコピーにするには要素を全てコピーする必要がある。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
import "fmt"
func main() {
m1 := make(map[string]int)
m1["a"] = 1
m1["b"] = 2
m2 := make(map[string]int)
for key, value := range m1 {
m2[key] = value
}
m2["c"] = 3
fmt.Println(m1) //map[b:2 a:1]
fmt.Println(m2) //map[c:3 a:1 b:2]
}

sliceのコピー

sliceも同様に参照型であるが、コピーするときはcopyメソッドを使える。

1
2
3
4
5
6
7
8
9
10
11
12
package main
import "fmt"
func main() {
s1 := []int{1, 2, 3}
s2 := make([]int, len(s1))
copy(s2, s1)
s2 = append(s2, 4)
fmt.Println(s1) //[1 2 3]
fmt.Println(s2) //[1 2 3 4]
}

参考

Maps - Go Language

go言語でoauth2パッケージを使う

oauth2パッケージ

go言語でoauth2を扱うのに便利なoauth2パッケージがあります。
今回は、これを使ってみたいと思います。
例として、Googleフォト(Picasa)のAPIを扱います。
ソースは下記を参照。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import (
"bufio"
"fmt"
"io/ioutil"
"log"
"os"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
func main() {
//ClientIDやClientSecretはGoogle API Console からコピーしてきます。
//Endpointはgoogle、github、facebookなどがoauth2配下のパッケージに用意されています。
config := oauth2.Config{
ClientID: "xxxxxxxxxxx",
ClientSecret: "yyyyyyyyyyyy",
Endpoint: google.Endpoint,
RedirectURL: "urn:ietf:wg:oauth:2.0:oob", //今回はリダイレクトしないためこれ
Scopes: []string{"https://picasaweb.google.com/data/"}, //必要なスコープを追加
}
//認証のURLを取得。AuthCodeURLには文字列を渡す。CSRF攻撃の回避のため、本当はリダイレクトのコールバックで検証する。
url := config.AuthCodeURL("test")
fmt.Println(url) //認証のURLを表示。ブラウザにコピペする
//リダイレクト先がないため、ブラウザで認証後に表示されるコードを入力
var s string
var sc = bufio.NewScanner(os.Stdin)
if sc.Scan() {
s = sc.Text()
}
//アクセストークンを取得
token, err := config.Exchange(oauth2.NoContext, s)
if err != nil {
log.Fatalf("exchange error")
}
client := config.Client(oauth2.NoContext, token) //httpクライアントを取得
//取得したclientでGetする
resp, err := client.Get("https://picasaweb.google.com/data/feed/api/user/default?start-index=1")
if err != nil {
log.Fatalf("client get error")
}
//レスポンスを表示
defer resp.Body.Close()
byteArray, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(byteArray))
}

どこでoauth2のアクセストークンを扱っているか

上記のソースではトークンを取得した後、config.Client()でhttp Clientを取得してそれを使うだけで、oauth2の通信が行えています。
どこで、アクセストークンをセットし、トークンの期限が切れていたらリフレッシュトークンを使うなどの処理をしているか気になります。
ソースコードを見ていくと、config.Client()の先、NewClient()でhttp.Clientを作成しているのが見えます。
ここで、http.ClientのTransportに独自のTransportを設定しているのがそれっぽいです。

1
2
3
4
5
6
7
8
9
10
func NewClient(ctx context.Context, src TokenSource) *http.Client {
//省略
return &http.Client{
Transport: &Transport{
Base: internal.ContextTransport(ctx),
Source: ReuseTokenSource(nil, src),
},
}
}

このTransportですが、RoundTripというメソッドを持っています。この辺について詳しくは以下のページを参照。
Go http.RoundTripper 実装ガイド
RoundTrip内を見ると、トークンが切れていたらリフレッシュしたり、Authorizationヘッダにアクセストークンをつけているのが追えます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
if t.Source == nil {
return nil, errors.New("oauth2: Transport's Source is nil")
}
token, err := t.Source.Token() //アクセストークンが切れていたらリフレッシュする
if err != nil {
return nil, err
}
req2 := cloneRequest(req)
token.SetAuthHeader(req2) //アクセストークンをAuthorizationヘッダに設定
t.setModReq(req, req2)
res, err := t.base().RoundTrip(req2)
if err != nil {
t.setModReq(req, nil)
return nil, err
}
res.Body = &onEOFReader{
rc: res.Body,
fn: func() { t.setModReq(req, nil) },
}
return res, nil
}

React.jsでshow、hide する

ボタン押下で要素をshow、hideする

いわゆるtoggleですね。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var Hello = React.createClass({
getInitialState: function(){
return {show: true};
},
onClick: function(e){
e.preventDefault();
this.setState({show: !this.state.show});
},
render: function() {
var span = this.state.show ? <span>hello</span> : null;
return(
<div>
<a href="" onClick={this.onClick.bind(this)}>show/hide</a>
{span}
</div>
);
}
});
ReactDOM.render(
<Hello/>,
document.getElementById('container')
);

あるいは、cssで行う。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var Hello = React.createClass({
getInitialState: function(){
return {show: true};
},
onClick: function(e){
e.preventDefault();
this.setState({show: !this.state.show});
},
render: function() {
return(
<div>
<a href="" onClick={this.onClick.bind(this)}>show/hide</a>
<span className={this.state.show ? "" : "hide"}>hello</span>
</div>
);
}
});
ReactDOM.render(
<Hello/>,
document.getElementById('container')
);

Visual Studio で保存時にフォーマットする

オートフォーマット

Visual Studio で ファイル保存時にコードをフォーマットしたい。
コードを自動的に整形することにより、ソースコードの品質を保ちたい。

Productivity Powers Tool のインストール

メニューの「ツール」→「拡張機能と更新プログラム」を選択。
「オンライン」から「Productivity Powers Tools」をダウンロードする。
(執筆時のバージョンはProductivity Powers Tools 2015)

設定

メニューの「ツール」→「オプション」に新しく「Productivity Powers Tools」があるので選択。
「PowerCommands」にある「Format document on save」 にチェック。

Format document on save

以上でOK。