# Golang Development SDGs(for beginners)
**インストール**
```console
$ echo `uname`_`arch` # OS と Arch を確認
Linux_amd64
$ curl -OL https://go.dev/dl/go1.17.5.linux-amd64.tar.gz
$ sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.17.5.linux-amd64.tar.gz
$ echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
$ exec $SHELL -l
$ go version
go version go1.17.5 linux/amd64
```
**SDGs で学ぶ Go 言語**
## 1. snake_case や Nazo_Snake_Case をやめよう
変数名: camelCase, PascalCase
private/public: camelCase, PascalCase
ファイル名: snake_case 例) `hoge_test.go`
## 2. 変数のスコープは狭くしよう
```go=
sum := 0
for i := 0; i < n; i++ {
// sum := 0
for j := 0; j < n; j++ {
sum += a[j]
}
fmt.Println(sum)
}
```
sum はスコープが広すぎる
## 3. スライスの iteration は for-range を使おう
```go=
a := []int{1, 2, 3}
for i := 0; i < len(a); i++ {
fmt.Println(a[i])
}
for i, elem := range a {
fmt.Println(elem)
// a[i]++
}
```
## 4. スライスのスライスはスライスで行おう
```go=
a := []int{1, 2, 3, 4}
b := []int{}
c := []int{}
for i := 0; i < 2; i++ {
b = append(b, a[i])
}
for i := 0; i < 2; i++ {
c = append(c, a[i])
}
b = a[:2]
c = a[2:]
```
## 5. 構造体はコンストラクタを作ろう
```go=
type Student struct {
Name string
Number int
}
func NewStudent(name string, num int) Student {
return Student {
Name: name,
Number: num,
}
}
stu := Student {
Name: "かじはらかじ",
Number: 70010000,
}
```
## 6. 構造体はメソッドで操作しよう
```go=
func Whoami(stu Student) {
fmt.Println(stu.Name)
}
Whoami(stu)
// これを使おう
func(stu *Student) Whoami() {
fmt.Println(stu.Name)
}
stu.Whoami()
```
**Break time**
これを Go でとこう https://atcoder.jp/contests/abc232/tasks/abc232_b
入力
```go=
var (
s string
t string
)
fmt.Scan(&s, &t)
set := map[int]struct{}{}
for i := 0; i < len(s); i++ {
d := int(t[i]) - int(s[i])
if d < 0 {
d += 26
}
set[d] = struct{}{}
}
fmt.Println(func() string {
if len(set) == 1 {
return "Yes"
} else {
return "No"
}
}())
```
## 7. エラーハンドリングはしっかりしよう
```go=
package main
import "strconv"
func main() {
num1, _ := strconv.Atoi("123")
num2, err := strconv.Atoi("abc")
if err != nil {
log.Println(err)
return
}
}
```
## 9. `*os.File` や `io.ReadCloser` は必ず読んで Close しよう
```go=
fp, err := os.Open("hoge.txt")
if err != nil {
log.Println(err)
return
}
// なんかの処理
fp.Close()
```
## 10. defer を使おう
defer ... スコープが終わった時に実行してくれるやつ
```go=
fp, err := os.Open("hoge.txt")
if err != nil {
log.Println(err)
return
}
defer fp.Close()
// なんかの処理
```
## 11. 関数化をしよう
```go=
func MyFunc(arg0 int, arg1 string) int {
return arg0
}
func MyAtoi(s string) (int, error) {
x := 0
err := nil
return (x, err) // だめ
return x, err // いいよ
}
```
**break time**
これをとこう https://atcoder.jp/contests/abc217/tasks/abc217_c
```rust=
input! {
n: usize,
p: [i32; n]
}
let mut q = vec![0; n];
for (i, &elem) in p.iter().enumerate() {
q[elem as usize - 1] = i + 1
}
println!(
"{}",
q.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(" ")
);
```
## 12. パッケージ単位でモジュール化をしよう
```console
$ mkdir gopher-project
$ cd gopher-project
$ go mod init gopher-project
```
```console
$ ls -T
project
├── go.mod
├── main.go
└── mymath
└── prime.go
```
mymath/prime.go
```go=
package mymath
// O(1)
func IsPrime(x int) bool {
return !(x % 2 == 0)
}
```
## 12.5 テスト
mymath/prime_test.go
```go=
package mymath
import "testing"
func TestIsPrime(t *testing.T) {
if !IsPrime(2) {
t.Error(e)
}
}
```
## 13. 引数では構造体はなるべくポインタで受け取ろう
## 14. gofmt でフォーマットを整えよう
go の基礎はここまで
---
## 16. クソデカ commit はやめよう
## 17. commit message にポエムを書くのはやめよう
これが結構おすすめ
https://qiita.com/numanomanu/items/45dd285b286a1f7280ed
## 18. main に push するのはやめよう
## 19. Pull Request で何をどうしたのか説明をしっかり書こう
## 20. コードレビューでいじめるのはやめよう