tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

【go】golangのエラー処理メモ - ①. errorとError型とカスタムErrorと

はじめに

goをさわって数ヶ月ですが、雰囲気では書けていたものの
errorやエラーハンドリングについてはもやもやしたままだったので自分理解メモの①

関連

この記事の関連です。

アジェンダ

  1. errorの基本の書き方
  2. Error型について
  3. 任意の文字列でError型を返す(errors.Newとfmt.Error)
  4. カスタムError

1. errorの基本の書き方

以下のコードがerrorについての基本です。

// Openに成功したらnil(エラー無し)が返される
// Openに失敗したらerror側の値が返却される
f, err := os.Open("filename.ext")
if err != nil {
    log.Fatal(err)
}

返されるerror変数とnilを比較することで操作が成功したか判断します。
上記で言えば if err != nil { です。

os.Openの定義は以下のようになっています。

func Open(name string) (file *File, err error)
https://golang.org/pkg/os/#Open

2. Error型について

errorはgoのビルトインのインターフェース型の1つです。

type error interface {
    Error() string
}

多くの内部パッケージにおいて使用されるerrorは
errorsパッケージ以下で実装されたプライベート構造体errorStringらしいです。

// Package errors implements functions to manipulate errors.
package errors

// New returns an error that formats as the given text.
func New(text string) error {
  return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
  s string
}

func (e *errorString) Error() string {
  return e.s
}

使う場合は、errors.Newを通して文字列をerrorStringに変換し
インターフェースerrorを満たすオブジェクトを得る、という感じになってます。

3. 任意の文字列でError型を返す(errors.Newとfmt.Error)

Error型について触れましたが、任意の文字列でerror型を返すには主に以下の2つがメジャーです。

用途としての大きな違いは、
fmt.Errorはフォーマットを指定したエラーを返せる ので
固定文字列でよければerrors.New、可変文字列を含めたければfmt.Errorという感じでしょうか。

以下で使ってみます。

errors.New

errors.Newに文字列を渡すだけです。

サンプル

https://github.com/tweeeety/go-error/blob/master/src/go-error/sample01/main.go

package main

import (
  "errors"
  "fmt"
)

func errorsNewSsample() error {
  err := errors.New("this is errors.New sample.")
  return err
}

func main() {
  err := errorsNewSsample()

  fmt.Println(err)
  fmt.Printf("%T\n", err)
}
出力
$ go run src/go-error/sample01/main.go 
this is errors.New sample.
*errors.errorString

fmt.Error

フォーマット文字列を渡せるので、変数の値を一緒に出したい場合などに使います。

サンプル

https://github.com/tweeeety/go-error/blob/master/src/go-error/sample02/main.go

package main

import (
  "fmt"
)

func fmtErrorfSsample(str string) error {
  err := fmt.Errorf("this is fmt.Errorf sample. str: %s", str)
  return err
}

func main() {
  err := fmtErrorfSsample("hogehoge")
  fmt.Println(err)
  fmt.Printf("%T\n", err)
}
出力
$ go run src/go-error/sample02/main.go 
this is fmt.Errorf sample. str: hogehoge
*errors.errorString

4. カスタムError

2. Error型についてで触れた通り
errorインターフェース満たすにはError()を実装すれば良いです。

この方法で任意のカスタムError型を作ります。

sample01/main.go
package main

import (
  "fmt"
)

// カスタムErrorの構造体
type MyError struct {
  Msg  string
  Code int
}

// error interfaceを実装
func (err *MyError) Error() string {
  return fmt.Sprintf("ERROR: %d %s", err.Code, err.Msg)
}

// 何かする処理
func doSomething() error {
  return &MyError{Msg: "doSomething is unexpected error", Code: 30001}
}

func main() {
  if err := doSomething(); err != nil {
    fmt.Println(err)
    fmt.Printf("%T\n", err)
  }
}
出力
$ go run src/go-error/sample03/main.go
ERROR: 30001 doSomething is unexpected error
*main.MyError

おわり

errorの扱いについてサラっとまとめました。
あまり長いと書くのも読むのも疲れるのでエラーハンドリングについては別記事でかきます\(^o^)/

参考

【mac】macでポート(port)を使用しているプロセス(pid)を調べる - 例) goapp serve

はじめに

localなmacで開発をしているとたまに既にport使用してるから立ち上げられんで!みたいなエラーがでる事があります。
そんなときにプロセスを調べるメモ

調べ方

先んじて結論ですが、lsof で調べます。
8080を使っているプロセスを知りたい時のコマンドです

sudo lsof -P -i:8080

こんな時 例

今回の例ですが、ポートを指定してlocalにサーバを立ち上げる とします。
もうちょっと具体的にすると、localなmacgolang x appengineの開発を行おうとしている、という例として進めます。

goapp serve hoge.yamlはlocalにサーバを立ち上げますが、
これはデフォルトで8080ポートを使用します。

いざ立ち上げようと思ったらこんなエラーが出ました。

$ goapp serve hoge.yaml 
INFO     2017-08-07 07:57:54,539 devappserver2.py:764] Skipping SDK update check.
INFO     2017-08-07 07:57:54,602 api_server.py:268] Starting API server at: http://localhost:62294
INFO     2017-08-07 07:57:54,606 api_server.py:700] Applying all pending transactions and saving the datastore
INFO     2017-08-07 07:57:54,606 api_server.py:703] Saving search indexes
Traceback (most recent call last):
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/dev_appserver.py", line 101, in <module>
    _run_file(__file__, globals())
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/dev_appserver.py", line 97, in _run_file
    execfile(_PATHS.script_file(script_name), globals_)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/devappserver2.py", line 1041, in <module>
    main()
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/devappserver2.py", line 1029, in main
    dev_server.start(options)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/devappserver2.py", line 825, in start
    options.grpc_apis)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/dispatcher.py", line 196, in start
    _module.start()
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/module.py", line 1198, in start
    self._balanced_module.start()
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/wsgi_server.py", line 330, in start
    self._start_all_fixed_port(host_ports)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/wsgi_server.py", line 367, in _start_all_fixed_port
    raise BindError('Unable to bind %s:%s' % self.bind_addr)
google.appengine.tools.devappserver2.wsgi_server.BindError: Unable to bind localhost:8080
error while running dev_appserver.py: exit status 1

Unable to bind localhost:8080 とあるのでポートがすでに使われている可能性はあるもののterminal上どこでも立ち上げてる形跡はない...という状況です。

そのときのコマンド例

8080を使用しているプロセスを調べます。

$ sudo lsof -P -i:8080 
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
Python  58645 hoge   11u  IPv6 0x51abc044e9105fdb      0t0  TCP localhost:8080 (LISTEN)
Python  58645 hoge   12u  IPv4 0x51abc044e8ae2963      0t0  TCP localhost:8080 (LISTEN)

このプロセスに思い当たりがなければ思い切ってkillします。

$ sudo kill -9 58645 58645

再度立ち上げてみると無事立ち上がりました。めでたし

$ goapp serve local_production.yaml 
INFO     2017-08-07 08:47:58,533 devappserver2.py:764] Skipping SDK update check.
INFO     2017-08-07 08:47:58,611 api_server.py:268] Starting API server at: http://localhost:62971
INFO     2017-08-07 08:47:58,616 dispatcher.py:199] Starting module "hoge" running at: http://localhost:8080
INFO     2017-08-07 08:47:58,621 admin_server.py:116] Starting admin server at: http://localhost:8000
WARNING  2017-08-07 08:47:58,621 devappserver2.py:836] No default module found. Ignoring.

オプション

申しわけ程度にlsofのオプションです。

オプション 説明
-c プロセス名を指定する
-i ネットワークソケットファイルを表示する
-n IPアドレスを表示する(名前解決しない)
-p プロセスIDを指定する
-P ポート番号をサービス名に変換しない

おわり

lsofはlinuxでも比較的よく使いますがオプション忘れては調べてるので備忘録的に書きました!

【SublimeText】jsHintとSublimeLinter-jshintを入れるメモ for mac

はじめに

久しぶりにsublimeが使いたい用途があり
今さらですがSublimeLinter-jshintを入れたので簡易手順メモ。

ちなみにES6などはESlintのほうが良いです。

アジェンダ

  1. jsHintをインストー
  2. jsHint/SublimeLinter/SublimeLinter-jshintについて
  3. SublimeLinterのインストー
  4. SublimeLinter-jshintのインストー
  5. 使ってみる

1. jsHintをインストー

jsHintのインストールはterminalコマンドで行います。

また、npmでインストールするのでnodeは必要ですが今回は省きます。
nodeとnpmが入っていれば以下のコマンドでjsHintインストールは終わりです。

# インストール
$ npm install -g jshint

# 確認
$ jshint -v
jshint v2.9.5

2. jsHint/SublimeLinter/SublimeLinter-jshintについて

休憩がてら自分用メモです。

jshintについて

jshintはコマンドで入れたように、SublimeLinter-jshint がなくても単体でjsHintとして動きます。

例えば以下コードを保存してjshintをコマンド実行する事もできます。

  • sample.js
(function(){
  "strict"
})();
  • 実行
# jsが入ってるディレクトリに対してjshint
$ jshint js_dir
js_dir/sample.js: line 2, col 11, Missing semicolon.

1 error

vimでも使えるので便利です。

SublimeTextについて

ここからはsublimeText上で行います。

SublimeTextでのパッケージインストールはPackage Controlが必要ですが、これも今回は省きます。

たまにしかSublimeを開かない自分用に
よく忘れるPackage Controlのショートカットも書いておきます。

Ctrl + Shift + p

SublimeLinterとSublimeLinter-jshintについて

SublimeLinterはリアルタイムにコードのエラーをチェックできるフレームワークのようなものです。
jsに限らず様々な言語のlinterとして動作しますが、言語ごとの設定を持っていません。

そこで、SublimeLinter-jshintというjavascript用のプラグインを追加で入れる事で
linter + javascriptな環境になります。

3. SublimeLinterのインストー

Package Controlから入れるだけです。

Ctrl + Shift + pでPackage Control開いてinstallと入力します。
Package Control: Install Packageを選択します。
f:id:tweeeety:20170725221240p:plain

ダイアログが開いたらSublimeLinterを選択してインストール完了です。 f:id:tweeeety:20170725221300p:plain

4. SublimeLinter-jshintのインストー

SublimeLinterと手順は同様です。

Ctrl + Shift + pでPackage Control開いてinstallと入力します。
Package Control: Install Packageを選択します。
ダイアログが開いたらSublimeLinter-jshintを選択してインストール完了です。

5. 使ってみる

使う前に、SublimeTextを再起動しておきます。
これをしないと動かないなーなんてことも。

適当なファイルを保存して開いてみると
先ほど書いたファイルを開いてみるとエラーの行数にオレンジのマークをしてくれます。 f:id:tweeeety:20170725221703p:plain

また、画面下部ににエラー内容も表示してくれます。

UTF-8, Error: Missing semicolon, Line2, Column11

おわり

久しぶりにsublime使いましたがパッケージのインストールもお手軽 \(^o^)/

【git】.gitignoreの書き方 - テンプレートを使うその3 - 任意のファイルを.gitignoreとして読み込む

はじめに

git管理化から特定のファイルなどを無視したければ.gitignoreに追加します。
しかもだいたいが適宜気づいたら、つどつど。

ただ、言語、フレームワーク、ツールなどのファイルは
新しいプロジェクトのたび x 適宜気づくたびに追加するのは面倒です。

そこで、
プロジェクトによらない.gitignoreしたいものはテンプレ化しておきたいですよね。
.gitignoreテンプレ化については以下を参考にしてみてください。

しかし、せっかくテンプレは手にいれたものの
vim使ってるの自分だけだしプロジェクトの.gitignoreを汚したくない…
そんなときのメモです。

やってみる

.gitignoreファイルはリポジトリ直下にある.gitignore以外にも
configのcore.excludesfileに任意のファイルを指定する事で無視してくれます。

なので、例えば$HOME/.gitignore_myというファイルを作り
そこに個人的なignoreリストを作成してconfigに登録しておくことで、
チーム共通のリポジトリ.gitignoreを汚さずにすみます

# 
$ cd `プロジェクトリポジトリ`

# ${プロジェクトディレクトリ}/.gitignoreの他に読み込むファイルを指定
$ git config --local core.excludesfile $HOME/.gitignore_my

# .git/configに追記されている
$ cat .git/config 
[core]
  ~ 省略 ~ 
  excludesfile = /Users/hoge/.gitignore_my
  ~ 省略 ~ 

こうしておけば
gitignore.iogiboので取得した自分だけが使ってるツールなどのgitignoreテンプレート設定を別にすることができます。

おわり

gitは長らく使ってるつもりでも知らない事が多いですね\(^o^)/

【git】.gitignoreの書き方 - テンプレートを使うその2 - gibo(gitignore boilerplates)

はじめに

git管理化から特定のファイルなどを無視したければ.gitignoreに追加します。
しかもだいたいが適宜気づいたら、つどつど。

ただ、言語、フレームワーク、ツールなどのファイルは
新しいプロジェクトのたび x 適宜気づくたびに追加するのは面倒です。

そこで、
今回はお決まりのgitignoreテンプレを提供してくれるgiboのメモ

アジェンダ

  1. giboとは
  2. giboを使ってみる for mac

1. giboとは

公式サイトはこちらです。 https://github.com/simonwhitaker/gibo

gibo (short for .gitignore boilerplates) is a shell script to help you easily access .gitignore boilerplates from github.com/github/gitignore.

公式からですが、giboはgithub.com/github/gitignoreのボイラープレートにアクセスしてくれるshell script とのことです。

むしろボイラープレートって言葉が初耳でした..w
ボイラープレートとは

2. giboを使ってみる for mac

使い方は簡単です。
macでhomebrewを使っているならbrew install giboとするだけです。

使ってみた感じです。

gibo入れる
# インストール
$ brew install gibo

# version確認してみる
# + 何か怒られるが、これは後述する-lすると.gitignore-boilerplatesが作られて解消されます
gibo --version
fatal: Cannot change to '/Users/hoge/.gitignore-boilerplates': No such file or directory
gibo 1.0.5 by Simon Whitaker <sw@netcetera.org>

# git -lでリスト確認
# + .gitignore-boilerplates の作成
$ gibo -l
fatal: Cannot change to '/Users/hoge/.gitignore-boilerplates': No such file or directory
Cloning https://github.com/github/gitignore.git to /Users/hoge/.gitignore-boilerplates
Cloning into '/Users/hoge/.gitignore-boilerplates'...
remote: Counting objects: 6896, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 6896 (delta 6), reused 11 (delta 2), pack-reused 6880
Receiving objects: 100% (6896/6896), 1.37 MiB | 299.00 KiB/s, done.
Resolving deltas: 100% (3687/3687), done.
Checking connectivity... done.
=== Languages ===

Actionscript    CommonLisp    Erlang      IGORPro     Maven     Prestashop    Scrivener   Unity
Ada     Composer    ExpressionEngine  Java      Mercury     Processing    Sdcc      UnrealEngine
Agda      Concrete5   ExtJs     Jboss     MetaProgrammingSystem PureScript    SeamGen     VisualStudio
Android     Coq     Fancy     Jekyll      Nanoc     Python      SketchUp    VVVV
AppceleratorTitanium  CraftCMS    Finale      Joomla      Nim     Qooxdoo     Smalltalk   Waf
AppEngine   CUDA      ForceDotCom   Julia     Node      Qt      Stella      WordPress
ArchLinuxPackages D     Fortran     KiCad     Objective-C   R     SugarCRM    Xojo
Autotools   Dart      FuelPHP     Kohana      OCaml     Rails     Swift     Yeoman
C++     Delphi      Gcov      LabVIEW     Opa     RhodesRhomobile   Symfony     Yii
C     DM      GitBook     Laravel     OpenCart    ROS     SymphonyCMS   ZendFramework
CakePHP     Drupal      Go      Leiningen   OracleForms   Ruby      Terraform   Zephir
CFWheels    Eagle     Gradle      LemonStand    Packer      Rust      TeX
ChefCookbook    Elisp     Grails      Lilypond    Perl      Sass      Textpattern
Clojure     Elixir      GWT     Lithium     Phalcon     Scala     TurboGears2
CMake     Elm     Haskell     Lua     PlayFramework   Scheme      Typo3
CodeIgniter   EPiServer   Idris     Magento     Plone     SCons     Umbraco

=== Global ===

Anjuta      CVS     Espresso    Lazarus     ModelSim    Redis     TextMate    Xcode
Ansible     DartEditor    FlexBuilder   LibreOffice   Momentics   SBT     TortoiseGit   XilinxISE
Archives    Dreamweaver   GPG     Linux     MonoDevelop   SlickEdit   Vagrant
Bazaar      Dropbox     JDeveloper    LyX     NetBeans    Stata     Vim
BricxCC     Eclipse     JEnv      macOS     Ninja     SublimeText   VirtualEnv
Calabash    EiffelStudio    JetBrains   Matlab      NotepadPP   SVN     VisualStudioCode
Cloud9      Emacs     Kate      Mercurial   Otto      SynopsysVCS   WebMethods
CodeKit     Ensime      KDevelop4   MicrosoftOffice   Redcar      Tags      Windows
[~ 15:44:06]$ gibo --version
gibo 1.0.5 by Simon Whitaker <sw@netcetera.org>
https://github.com/simonwhitaker/gibo

# 再度versionを確認
$ gibo --version
gibo 1.0.5 by Simon Whitaker <sw@netcetera.org>
https://github.com/simonwhitaker/gibo
gibo使う

vim用のgitignoreを出力してみる

$ gibo vim
### https://raw.github.com/github/gitignore/8edb8a95c4c4b3dce71a378aaaf89275510b9cef/Global/vim.gitignore

# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]

# Session
Session.vim

# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
その他

見ての通り標準出力に出力されるだけなので自分で追記してやります。

$ gibo vim >> .gitignore

また、適宜updateして更新してあげましょう。

$ gibo -u

おわり

こういうテンプレは自分でメンテしてくのも大変だし
お任せできるって素敵ですね\(^o^)/

【git】.gitignoreの書き方 - テンプレートを使うその1 - gitignore.io

はじめに

git管理化から特定のファイルなどを無視したければ.gitignoreに追加します。
しかもだいたいが適宜気づいたら、つどつど。

ただ、言語、フレームワーク、ツールなどのファイルは
新しいプロジェクトのたび x 適宜気づくたびに追加するのは面倒です。

そこで、
今回はお決まりのgitignoreテンプレを提供してくれるgitignore.ioのメモ f:id:tweeeety:20170622002147p:plain

アジェンダ

  1. gitignore.ioとは
  2. gitignore.ioをcurlで使ってみる
  3. gitignore.ioをbashのコマンドにする
  4. gitignore.ioをgit aliasにしてgit ignore xxxで使えるようにする

1. gitignore.ioとは

公式サイトはこちらです。 https://www.gitignore.io/

Create useful .gitignore files for your project

公式ページからの引用ですが、有用な.gitignoreを作ってくれる君ですね。

また、テンプレ集という意味だと
https://github.com/github/gitignore もあるので見てみると良いかもしれないです。

2. gitignore.ioをcurlで使ってみる

使い方は簡単。
https://www.gitignore.io/api/${言語やツール} と指定するだけです。

ためしにvim用のgitignore

$ curl -L -s https://www.gitignore.io/api/vim

# Created by https://www.gitignore.io/api/vim

### Vim ###
# swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags

# End of https://www.gitignore.io/api/vim

標準出力に出力されるので、そのまま.gitignoreを作るなり追記するなりでも良さそうです。

# 追記
curl -L -s https://www.gitignore.io/api/vim >> .gitignore

また、同時に複数指定することもできます。

$ curl -L -s https://www.gitignore.io/api/vim,java

# Created by https://www.gitignore.io/api/vim,java

### Java ###
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

### Vim ###
# swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags

# End of https://www.gitignore.io/api/vim,java

3. gitignore.ioをbashのコマンドにする

公式のまんまですが下のようにbashのfunctionにしてしまいます。

echo "function gi() { curl -L -s https://www.gitignore.io/api/\$@ ;}" >> ~/.bash_profile && source ~/.bash_profile

使ってみる

# bashの設定に追加
$ echo "function gi() { curl -L -s https://www.gitignore.io/api/\$@ ;}" >> ~/.bash_profile && source ~/.bash_profile

# 打ってみる
$ gi vim

# Created by https://www.gitignore.io/api/vim

### Vim ###
# swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags

# End of https://www.gitignore.io/api/vim

4. gitignore.ioをgit aliasにしてgit ignore xxxで使えるようにする

bash的なコマンドも良いですが、どうせならgitコマンドぽく使いたいですよね。

こちらも公式のまんまですが、
以下のようにするとgitのsubコマンドのように使えます。

git config --global alias.ignore '!gi() { curl -L -s https://www.gitignore.io/api/$@ ;}; gi'

使ってみる

# aliasにする前
# 当然怒られる
$ git ignore vim
git: 'ignore' is not a git command. See 'git --help'.

# aliasにする
$ git config --global alias.ignore '!gi() { curl -L -s https://www.gitignore.io/api/$@ ;}; gi'

# どや!
$ git ignore vim

# Created by https://www.gitignore.io/api/vim

### Vim ###
# swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags

# End of https://www.gitignore.io/api/vim

おわり

こういうテンプレは自分でメンテしてくのも大変だし
お任せできるって素敵ですね\(^o^)/

【go】funcの引数にstructの値渡し、ポインタ渡ししたときの挙動メモ

はじめに

goをなんとなく書き始めて半年経っていないくらいですが、
Goでxxxのポインタを取っているプログラムはだいたい全部間違っている という記事を見てなるほどなーと思いました。

最初のころとか確かに何となく無駄にポインタで渡していた気がする…

と、思ったところで、structについても自分で再確認するかーと思ったので
funcの引数にstructの値渡しとポインタ渡しで挙動を確かめてみるだけのgo初心者メモ

ソース

structを値として渡す場合とポインタとして渡す場合のいくつかだけの単純サンプル

package main

import "log"

type Data struct {
  Name string
  Age  int64
}

// #1.
//   arg :値渡し
//   処理:値のままプロパティアクセスして代入
func changeNameArgNormalAccessNormal(d Data) {
  d.Name = "fuga"
}

// #2.
//   arg :値渡し
//   処理:ポインタにしてからプロパティアクセスして代入
func changeNameArgNormalAccessPointer(d Data) {
  dPointer := &d
  dPointer.Name = "fuga"
}

// #3.
//   arg :ポインタ渡し
//   処理:値にしてからプロパティアクセスして代入
func changeNameArgPointerAccessNormal(dPointer *Data) {
  d := *dPointer
  d.Name = "fuga"
}

// #4.
//   arg :ポインタ渡し
//   処理:ポインタのままプロパティアクセスして代入
func changeNameArgPointerAccessPointer(dPointer *Data) {
  dPointer.Name = "fuga"
}

func main() {
  // #1
  d1 := Data{Name: "hoge", Age: 20}
  changeNameArgNormalAccessNormal(d1)
  log.Printf("d1: %+v", d1)

  // #2
  d2 := Data{Name: "hoge", Age: 20}
  changeNameArgNormalAccessPointer(d2)
  log.Printf("d2: %+v", d2)

  // #3
  d3 := Data{Name: "hoge", Age: 20}
  changeNameArgPointerAccessNormal(&d3)
  log.Printf("d3: %+v", d3)

  // #4
  d4 := Data{Name: "hoge", Age: 20}
  changeNameArgPointerAccessPointer(&d4)
  log.Printf("d4: %+v", d4)
}

https://github.com/tweeeety/go-struct-ref-sample

結果

#4 だけが元のコードの結果も変わります。
まぁ、そうだよね、というくらいでした。

$ go run struct_ref.go 
2017/06/21 23:53:22 d1: {Name:hoge Age:20}
2017/06/21 23:53:22 d2: {Name:hoge Age:20}
2017/06/21 23:53:22 d3: {Name:hoge Age:20}
2017/06/21 23:53:22 d4: {Name:fuga Age:20}

おわり

最初のころmapあたりは無駄にポインタにしたことがある気もしなくもない\(^o^)/