ラベル golang の投稿を表示しています。 すべての投稿を表示
ラベル golang の投稿を表示しています。 すべての投稿を表示

2024/03/03

2023/10/12

2023/07/06

vscode ,gvm ,GOROOT

gvm install go19.2
gvm list
gvm use go19.2 --default

=>GOROOT、GOPATH will be set by gvm automatically

vsCode will use the go defined by $GOROOT

2022/12/15

golang option pattern

 - golang option pattern

- option struct
```
type option struct {
Name string
Age int
}
```
- option func type
```
type Option func(*options)

func F1(name string) Option{
return fun(op *option){
op.Name = name
}
}
}

func F2(age int) Option{
return func(op *option) {
op.Age= age
}
}
```
- usage
```
func NewOption(setters ...Option){
op := &option{}
for s:=range setters{
s(op)
}
return op
}

NewOption(F1("tom"),F2(18))
```

2022/12/14

golang chunk

 - chunk

```
func Chunk[T any](items []T, chunkSize int) [][]T {
var chunks = make([][]T, 0, (len(items)/chunkSize)+1)
for chunkSize < len(items) {
items, chunks = items[chunkSize:], append(chunks, items[0:chunkSize:chunkSize])
}
return append(chunks, items)
}
//Arrayをスライシングすると、リターンされたSliceのcapはstartIndexからArrayの最期までのサイズです。
//しかし、次のようにスライシングする時、maxIndexを追加してcapのサイズを調整することが出来ます。
//slice[startIndex:endIndex:maxIndex]
```

big array goroutine

 - https://qiita.com/tutuz/items/057452fbbe9a5ae26d37

- multi goroutine to loop array
```
slice := []string{"a", "b", "c", "d", "e"}
sliceLength := len(slice)
var wg sync.WaitGroup
wg.Add(sliceLength)
fmt.Println("Running for loop…")
for i := 0; i < sliceLength; i++ {
go func(i int) {
defer wg.Done()
val := slice[i]
fmt.Printf("i: %v, val: %v\n", i, val)
}(i)
}
wg.Wait()
fmt.Println("Finished for loop")
```
- 課題はエラー検知とgoroutineの数の制御、errgroupの登場
- golang.org/x/sync/errgroup は、複数の goroutine を実行して、それらのうちにエラーがあったときにエラーを知る、ということを可能にしてくれるライブラリ
- sync.WaitGroup は実行した goroutine が終わるのを待ちますが、エラーがあったかどうかはわかりません
- errgroup は sync.WaitGroup+error といったイメージで、どれかの goroutine でエラーがあったら最初のひとつを知ることができ
```
// You can edit this code!
// Click here and start typing.
package main

import (
"context"
"fmt"

"golang.org/x/sync/errgroup"
"golang.org/x/sync/semaphore"
)

func main() {
fmt.Println("Hello, 世界")
ctx := context.TODO()
ms := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
mcs := make([]int, len(ms))

eg := errgroup.Group{}
sem := semaphore.NewWeighted(3)
for i := range ms {
if err := sem.Acquire(ctx, 1); err != nil {
panic(err)
}
func(i int) {
eg.Go(
func() error {
defer sem.Release(1)
fmt.Printf("i is %v\n", i)
mcs[i] = ms[i] + 100
return nil
})
}(i)
}

if err := eg.Wait(); err != nil {
panic(err)
}
fmt.Printf("ms is %v\n", ms)
fmt.Printf("msc is %v\n", mcs)
}
```

2022/12/08

golang fmt %q

文字列を””で囲んで出力する。
これで実際の を””に表現して、わかりやすい 

spannerのgolang clientで%qを使っている
It's just quite a strange decision made by Google here, to assume that the String() function is only used for logging and it's ok to add quotes...

package main


import (

"fmt"

)


func main() {

str := "Gopherくん"

slice := []string{"g", "o", "h", "e", "r"}

integer := 12450

fmt.Printf("1:出力は %q となります。\n", str)

fmt.Printf("2:出力は %s となります。\n", str)


fmt.Printf("3:出力は %q となります。\n", slice)

fmt.Printf("4:出力は %s となります。\n", slice)


fmt.Printf("5:出力は %d となります。\n", integer)

fmt.Printf("6:出力は %q となります。\n", integer)

}


//1:出力は "Gopherくん" となります。

//2:出力は Gopherくん となります。

//3:出力は ["g" "o" "h" "e" "r"] となります。

//4:出力は [g o h e r] となります。

//5:出力は 12450 となります。

//6:出力は 'ア' となります。 (アのunicode の十進制は12345)


2022/12/07

spanner nullable data type golang

 spanner nullable data type

```
// NullableValue is the interface implemented by all null value wrapper types.
type NullableValue interface {
// IsNull returns true if the underlying database value is null.
IsNull() bool
}
```
- how to use
- difference between null,"","someValue"
- null
- spanner.NullString(valid=false)
- ""
- spanner.NullString(valid=true,value="")
- update(value[*NullableValue]->model[NullableValue])
- update target items
- value is not nil
- not update target items
- value is nil
- vo is all pointer

by the way, another orm tool,gorm , don't solve this problem well.
var user User
db.First(&user)

db.Model(&user).Updates(User{Age: 18, Name: nil})
// 実行 SQL : UPDATE `users` SET `age` = '18'  WHERE `users`.`id` = '1'

GORM のドキュメントを見ると以下のように書いてあったので、構造体で実行すると無視されてしまうようです。 When query with struct, GORM will only query with those fields has non-zero value,

that means if your field's value is 0, '', false or other zero values,

it won't be used to build query conditions,

go instal where ?

go install xxx..xxx

==>the location is ~/go/bin
so ,set the ~/go/bin to .bash_profiles 's PATH


go version

go help environment

```

GOBIN

The directory where 'go install' will install a command.

GOPATH

For more details see: 'go help gopath'.

GOROOT

The root of the go tree.

```

go help gopath

```

If the environment variable is unset, GOPATH defaults

to a subdirectory named "go" in the user's home directory

($HOME/go on Unix, %USERPROFILE%\go on Windows),

unless that directory holds a Go distribution.

Run "go env GOPATH" to see the current GOPATH.

```

go env GOPATH

==>~/go

go help install

````

usage: go install [build flags] [packages]


Install compiles and installs the packages named by the import paths.


Executables are installed in the directory named by the GOBIN environment

variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH

environment variable is not set. Executables in $GOROOT

are installed in $GOROOT/bin or $GOTOOLDIR instead of $GOBIN.

```

golang model

https://go.dev/play/p/B7ErJjt8JqU 

modelの役割ですが、
① entity,usecase,repo,querierなど繋ぐ
② validationなどの業務ロジックの担保
②の配慮でmodelのfiledは非公開で、Setter都度Validationする、常に完璧な状態を求めて、
trade-offで使いにくく、①の役割を損する。
なので、①の役割をPrimativeなstruct(一旦voと呼ぶ)に分担する方いいかなと思う。
vo<=>modelの変換は手間ですが、複雑ではないので、ある程度自動作成できる。

-- go.mod --

module sample

go 1.19
-- model/name.go --
package model

import "errors"

type Name struct {
string
}

func NewName(v string) (Name, error) {
n := Name{v}
if err := n.validate(); err != nil {
return Name{}, err
}

return n, nil
}

func (n Name) validate() error {
if len(n.string) > 10 {
return errors.New("name length must be less than equal 10")
}
return nil
}

func (n Name) String() string {
return n.string
}
-- model/user.go --
package model

import "errors"

// entity
type User struct {
id string
name Name
age *int
}

func (u User) validate() error {
if u.id == "" {
return errors.New("id must not be empty")
}
if err := u.name.validate(); err != nil {
return err
}
return nil
}

func NewUser(vo UserVO) (User, error) {
return vo.ToModel()
}

func InitUser(vo UserVO) (User, error) {
vo.ID = "1234567890" // random
return vo.ToModel()
}

func (u User) ToVO() UserVO {
return UserVO{
ID: u.id,
Name: u.name.String(),
Age: u.age,
}
}

type UserVO struct {
ID string
Name string
Age *int
}

func (uvo UserVO) ToModel() (User, error) {
u := User{
id: uvo.ID,
name: Name{uvo.Name},
age: uvo.Age,
}
if err := u.validate(); err != nil {
return User{}, err
}
return u, nil
}
-- main.go --
package main

import (
"fmt"
"sample/model"
)

func main() {
fmt.Println("success pattern")
age := 12
//New
vo := model.UserVO{
ID: "s11600",
Name: "kume",
Age: &age}
u, err := model.NewUser(vo)
if err != nil {
fmt.Println("err:", err)
}
fmt.Printf("valid user, %+v\n", u)

//Init
vo = model.UserVO{
Name: "ku",
Age: &age}
u, err = model.InitUser(vo)
if err != nil {
fmt.Println("err:", err)
}
fmt.Printf("valid user, %+v\n", u)

//update
vo = u.ToVO()
vo.Name = "updated"
vo.Age = nil
u, err = vo.ToModel()
if err != nil {
fmt.Println("err:", err)
}
fmt.Printf("update success, %+v\n", u)



fmt.Println("--------------")
fmt.Println("failed pattern")
vo.Name = "invalid name"
u, err = vo.ToModel()
if err != nil {
fmt.Println("err:", err)
}
fmt.Printf("update failed, %+v\n", u)
}


2020/10/16

golang sha256

 package main

import (

"fmt"
        "crypto/sha256"
)


func main() {

        //saltで値変わるね

       salt:="test"
       hash := hmac.New(sha256.New, []byte("1"))

hash.Write([]byte(salt))
        fmt.Printf("%x\n", hash.Sum(nil))

}


mac のshasumで無理かな?
goplaygroud でやりました。

2020/05/29

golang var is nil

package main

import (
"fmt"
)

func main() {
var stringArr []string

       //true
fmt.Println(stringArr==nil)

// zero
fmt.Println(len(stringArr)) 
}

make([]string,0) is not nil, len is zero

2019/12/18

golang gorm update when record not exist

when record is not exist. update will be success.
have to check RowsAffected .
the same as delte

query := db.Model(r).Updates(something)
if query.Error != nil {
   return query.Error
}
if query.RowsAffected == 0 {
   return gorm.ErrRecordNotFound
}



query := db.Delete(&something{ID: ID})
if query.Error != nil {
   return query.Error
}
if query.RowsAffected == 0 {
   return gorm.ErrRecordNotFound
}

2019/11/19

gorm 问题



  • 多了许多()  query := db.debug.Where(fmt.Sprintf("id in ( %s )", “1,2,3”))=>SELECT * FROM `a`  WHERE `a`.`deleted_at` IS NULL AND ((id in ( 1,2,3 )))
  • preload 时ID一大堆



2019/09/02

2019/06/25

gvm change gopath

go env
gvm pkgset list
gvm pkgenv xxx
edit it
gvm pkgset use xxx

2019/03/27

gin,appengine,graphql test


gin+GAE+graphql のテスト下記で行けった。


appEngineTestInstance
->instance.NewRequest
gin.Context(request)
context.Set(key value)

```
ins, _ := aetest.NewInstance(nil)
req, _ := ins.NewRequest("", "", nil)

var context *gin.Context
context = &gin.Context{Request: req}
b, _ := json.Marshal(x.y{z: "1"})
context.Set("key", b)
```

2019/03/05

Removing packages installed with go get

juse delete the source and package
麻烦,要是有一个命令就好了,找一下

It's safe to just delete the source directory and compiled package file. Find the source directory under $GOPATH/src and the package file under $GOPATH/pkg/<architecture>, for example: $GOPATH/pkg/windows_amd64.


example
go get github.com/golang/mock/mockgen


go clean -i github.com/golang/mock/mockgen

The -i flag causes clean to remove the corresponding installed
archive or binary (what 'go install' would create).

The -n flag causes clean to print the remove commands it would execute,
but not run them.

The -r flag causes clean to be applied recursively to all the
dependencies of the packages named by the import paths.


The -x flag causes clean to print remove commands as it executes them.

不知道安装的packagePath的话,找一下$GOPATH/pkg/windows_amd64啥的

2019/02/21

golang pointer compare

Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil