'Programming/golang'에 해당되는 글 70건

  1. 2023.05.24 golang waitgroup
  2. 2023.05.24 golang echo server middleware
  3. 2023.05.24 golang 동시성
  4. 2023.05.16 golang 고루틴과 채널
  5. 2023.05.16 golang switch, select
  6. 2023.05.16 golang uds
  7. 2023.05.16 golang mutex (sync)
  8. 2023.05.11 go 포맷터
  9. 2023.05.08 golang echo directory listing
  10. 2023.03.28 golang websocket binary
Programming/golang2023. 5. 24. 16:10

고루틴이 종료되는 시점을 확인하는 방법으로 보면 되려나?

 

여러개의 고루틴을 종료할때 까지 기다리기 위해  wait gorup을 이용할 수 있다.

package main

import (
    "fmt"
    "sync"
    "time"
)

func worker(id int) {
    fmt.Printf("Worker %d starting\n", id)

    time.Sleep(time.Second)
    fmt.Printf("Worker %d done\n", id)
}

func main() {

    var wg sync.WaitGroup

    for i := 1; i <= 5; i++ {
        wg.Add(1)

        i := i

        go func() {
            defer wg.Done()
            worker(i)
        }()
    }

    wg.Wait()

}

[링크 : https://gobyexample.com/waitgroups]

[링크 : https://pyrasis.com/book/GoForTheReallyImpatient/Unit35/06]

[링크 : https://pkg.go.dev/sync#WaitGroup.Add]

'Programming > golang' 카테고리의 다른 글

golang echo server middleware  (0) 2023.05.24
golang 동시성  (0) 2023.05.24
golang 고루틴과 채널  (0) 2023.05.16
golang switch, select  (0) 2023.05.16
golang uds  (0) 2023.05.16
Posted by 구차니

댓글을 달아 주세요

Programming/golang2023. 5. 24. 15:41

golang의 echo를 이용해서 웹서버 만드는건 쉬운데

서버 돌려 두면 별도의 go routine으로 돌테니 어떻게 구성을 해야

IPC를 통해 받은 변수를 깨지지 않게 처리할 수 있을까?

 

걍 결론은.. mutex로 귀결인가?

func (s *Stats) Handle(c echo.Context) error {
s.mutex.RLock()
defer s.mutex.RUnlock()
return c.JSON(http.StatusOK, s)
}

func main() {
e := echo.New()

// Debug mode
e.Debug = true

//-------------------
// Custom middleware
//-------------------
// Stats
s := NewStats()
e.Use(s.Process)
e.GET("/stats", s.Handle) // Endpoint to get stats

// Server header
e.Use(ServerHeader)

// Handler
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})

// Start server
e.Logger.Fatal(e.Start(":1323"))
}

[링크 : https://echo.labstack.com/cookbook/middleware/]

'Programming > golang' 카테고리의 다른 글

golang waitgroup  (0) 2023.05.24
golang 동시성  (0) 2023.05.24
golang 고루틴과 채널  (0) 2023.05.16
golang switch, select  (0) 2023.05.16
golang uds  (0) 2023.05.16
Posted by 구차니

댓글을 달아 주세요

Programming/golang2023. 5. 24. 15:38

atomic 패키지는 특정 변수의 값 증가등에 대해서 atomic operation 해주는 것 같고 copy는 없는 것 같고

sync.mutex가 역시 가장 무난한 선택인가 싶다.

channel은 내가 원하는 패키지에서 사용가능한 방법은 아난 것 같군..

 

atomic > mutex > channel

[링크 : https://woojinger.tistory.com/100]

[링크 : https://dev-yakuza.posstree.com/ko/golang/goroutine/]

[링크 : https://pkg.go.dev/sync/atomic]

'Programming > golang' 카테고리의 다른 글

golang waitgroup  (0) 2023.05.24
golang echo server middleware  (0) 2023.05.24
golang 고루틴과 채널  (0) 2023.05.16
golang switch, select  (0) 2023.05.16
golang uds  (0) 2023.05.16
Posted by 구차니

댓글을 달아 주세요

Programming/golang2023. 5. 16. 15:39

채널의 경우 1개로 해두면 하나가 들어갈 때 까지 해당 위치에서 블로킹 된다.

아래 예제는 받는 부분을 삭제했는데 그렇기에 채널을 통해 전송은 되지만 수신하지 않아 비워지지 않기 때문에

one을 출력하지 못하고 멈춰있는 것을 확인할 수 있다.

package main

import (
f "fmt"
"time"
)

func main() {

f.Println("select")

c1 := make(chan string)
c2 := make(chan string)

go func() {
time.Sleep(time.Second * 1)
f.Println("---")
c1 <- "one"
f.Println("one")
c1 <- "two"
f.Println("two")
c1 <- "three"
f.Println("three")
c1 <- "four"
f.Println("four")
}()

go func() {
time.Sleep(time.Second * 2)
c2 <- "fifth"
}()

for i := 0; i < 10000000000; i++ {
time.Sleep(time.Second)
}

}
$ go run go.go 
select
---
^Csignal: interrupt

 

다만, make를 통해 채널 버퍼를 n개로 만들어 두면, 넣을 수 있는 동안은 넣고 블로킹 되지 않고 넘어갈 수 있다.

package main

import (
f "fmt"
"time"
)

func main() {

f.Println("select")

c1 := make(chan string, 4)
c2 := make(chan string)

go func() {
time.Sleep(time.Second * 1)
f.Println("---")
c1 <- "one"
f.Println("one")
c1 <- "two"
f.Println("two")
c1 <- "three"
f.Println("three")
c1 <- "four"
f.Println("four")
}()

go func() {
time.Sleep(time.Second * 2)
c2 <- "fifth"
}()

for i := 0; i < 10000000000; i++ {
time.Sleep(time.Second)
}

}
$ go run go.go 
select
---
one
two
three
four
^Csignal: interrupt

 

[링크 : https://judo0179.tistory.com/88]

'Programming > golang' 카테고리의 다른 글

golang echo server middleware  (0) 2023.05.24
golang 동시성  (0) 2023.05.24
golang switch, select  (0) 2023.05.16
golang uds  (0) 2023.05.16
golang mutex (sync)  (0) 2023.05.16
Posted by 구차니

댓글을 달아 주세요

Programming/golang2023. 5. 16. 11:32

golang switch는 신형 언어에 확장되서 그런가 꽤나 만능이다.

특이하게 조건식도 가능하고, 케이스 리스트도 된다.(c#에서 얼핏 봤던 느낌..)

package main

import (
"fmt"
"time"
)

func main() {
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
}

[링크 :https://go.dev/tour/flowcontrol/11]

 

func WhiteSpace(c rune) bool {
switch c {
case ' ', '\t', '\n', '\f', '\r':
return true
}
return false
}

[링크 : https://hamait.tistory.com/1017]

 

아무튼 select는 channel 처리에 좀더 특화된 구문으로 생긴것 자체는 switch - case와 동일하게 작성된다.

다만, 동시에 여러개가 들어왔을 경우 랜덤하게 실행된다고 한다.

(생각이 꼬였는지 동시에 들어오면 가장 위에꺼 부터 실행되어야 하는거 아냐? 싶은데 동시성이니까 랜덤하게 처리되는건가..)

The select statement lets a goroutine wait on multiple communication operations.

A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.

 

package main

import "fmt"

func fibonacci(c, quit chan int) {
x, y := 0, 1
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}

func main() {
c := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
fibonacci(c, quit)
}

[링크 : https://go.dev/tour/concurrency/5]

 

[링크 : https://edu.goorm.io/learn/lecture/2010/한-눈에-끝내는-고랭-기초/lesson/382961/채널-select문]

 

'Programming > golang' 카테고리의 다른 글

golang 동시성  (0) 2023.05.24
golang 고루틴과 채널  (0) 2023.05.16
golang uds  (0) 2023.05.16
golang mutex (sync)  (0) 2023.05.16
go 포맷터  (0) 2023.05.11
Posted by 구차니

댓글을 달아 주세요

Programming/golang2023. 5. 16. 10:46

쓸만하려나?

server client
package main

import (
"fmt"
"log"
"os"
"path/filepath"
"time"

"github.com/google/uuid"
"github.com/johnsiilver/golib/ipc/uds"
)

func main() {
socketAddr := filepath.Join(os.TempDir(), uuid.New().String())

cred, _, err := uds.Current()
if err != nil {
panic(err)
}

// This will set the socket file to have a uid and gid of whatever the
// current user is. 0770 will be set for the file permissions (though on some
// systems the sticky bit gets set, resulting in 1770.
serv, err := uds.NewServer(socketAddr, cred.UID.Int(), cred.GID.Int(), 0770)
if err != nil {
panic(err)
}

fmt.Println("Listening on socket: ", socketAddr)

// This listens for a client connecting and returns the connection object.
for conn := range serv.Conn() {
conn := conn

// We spinoff handling of this connection to its own goroutine and
// go back to listening for another connection.
go func() {
// We are checking the client's user ID to make sure its the same
// user ID or we reject it. Cred objects give you the user's
// uid/gid/pid for filtering.
if conn.Cred.UID.Int() != cred.UID.Int() {
log.Printf("unauthorized user uid %d attempted a connection", conn.Cred.UID.Int())
conn.Close()
return
}
// Write to the stream every 10 seconds until the connection closes.
for {
if _, err := conn.Write([]byte(fmt.Sprintf("%s\n", time.Now().UTC()))); err != nil {
conn.Close()
}
time.Sleep(10 * time.Second)
}
}()
}
}
package main

import (
"flag"
"fmt"
"io"
"os"

"github.com/johnsiilver/golib/ipc/uds"
)

var (
addr = flag.String("addr", "", "The path to the unix socket to dial")
)

func main() {
flag.Parse()

if *addr == "" {
fmt.Println("did not pass --addr")
os.Exit(1)
}

cred, _, err := uds.Current()
if err != nil {
panic(err)
}

// Connects to the server at socketAddr that must have the file uid/gid of
// our current user and one of the os.FileMode specified.
client, err := uds.NewClient(*addr, cred.UID.Int(), cred.GID.Int(), []os.FileMode{0770, 1770})
if err != nil {
fmt.Println(err)
os.Exit(1)
}

// client implements io.ReadWriteCloser and this will print to the screen
// whatever the server sends until the connection is closed.
io.Copy(os.Stdout, client)
}

[링크 : https://github.com/johnsiilver/golib/blob/v1.1.2/ipc/uds/example/server/server.go]

[링크 : https://github.com/johnsiilver/golib/blob/v1.1.2/ipc/uds/example/client/client.go]

[링크 : https://pkg.go.dev/github.com/johnsiilver/golib/ipc/uds]

'Programming > golang' 카테고리의 다른 글

golang 고루틴과 채널  (0) 2023.05.16
golang switch, select  (0) 2023.05.16
golang mutex (sync)  (0) 2023.05.16
go 포맷터  (0) 2023.05.11
golang echo directory listing  (0) 2023.05.08
Posted by 구차니

댓글을 달아 주세요

Programming/golang2023. 5. 16. 10:36

 

package main

import (
"fmt"
"sync"
"time"
)

// SafeCounter is safe to use concurrently.
type SafeCounter struct {
mu sync.Mutex
v  map[string]int
}

// Inc increments the counter for the given key.
func (c *SafeCounter) Inc(key string) {
c.mu.Lock()
// Lock so only one goroutine at a time can access the map c.v.
c.v[key]++
c.mu.Unlock()
}

// Value returns the current value of the counter for the given key.
func (c *SafeCounter) Value(key string) int {
c.mu.Lock()
// Lock so only one goroutine at a time can access the map c.v.
defer c.mu.Unlock()
return c.v[key]
}

func main() {
c := SafeCounter{v: make(map[string]int)}
for i := 0; i < 1000; i++ {
go c.Inc("somekey")
}

time.Sleep(time.Second)
fmt.Println(c.Value("somekey"))
}

[링크 : https://go.dev/tour/concurrency/9]

 

func (*Mutex) Lock ¶
func (m *Mutex) Lock()
Lock locks m. If the lock is already in use, the calling goroutine blocks until the mutex is available.

func (*Mutex) TryLock ¶
added in go1.18
func (m *Mutex) TryLock() bool
TryLock tries to lock m and reports whether it succeeded.

Note that while correct uses of TryLock do exist, they are rare, and use of TryLock is often a sign of a deeper problem in a particular use of mutexes.

func (*Mutex) Unlock ¶
func (m *Mutex) Unlock()
Unlock unlocks m. It is a run-time error if m is not locked on entry to Unlock.

A locked Mutex is not associated with a particular goroutine. It is allowed for one goroutine to lock a Mutex and then arrange for another goroutine to unlock it.

[링크 : https://pkg.go.dev/sync#Mutex.Lock]

 

[링크 : https://mingrammer.com/gobyexample/mutexes/]

[링크 : https://www.joinc.co.kr/w/GoLang/example/mutexex]

[링크 : https://pyrasis.com/book/GoForTheReallyImpatient/Unit35]

 

'Programming > golang' 카테고리의 다른 글

golang switch, select  (0) 2023.05.16
golang uds  (0) 2023.05.16
go 포맷터  (0) 2023.05.11
golang echo directory listing  (0) 2023.05.08
golang websocket binary  (0) 2023.03.28
Posted by 구차니

댓글을 달아 주세요

Programming/golang2023. 5. 11. 11:56

go 에는 자체적으로 포맷터가 들어있다.

획일화 되서 나쁘다고 해야하나.. 좋다고 해야하나.. 참 미묘~

 

To format your code, you can use the gofmt tool directly:

gofmt -w yourcode.go
Or you can use the “go fmt” command:

go fmt path/to/your/package

[링크 : https://go.dev/blog/gofmt]

'Programming > golang' 카테고리의 다른 글

golang uds  (0) 2023.05.16
golang mutex (sync)  (0) 2023.05.16
golang echo directory listing  (0) 2023.05.08
golang websocket binary  (0) 2023.03.28
golang 크로스 컴파일 GOARM GOARCH  (0) 2023.02.03
Posted by 구차니

댓글을 달아 주세요

Programming/golang2023. 5. 8. 10:30

e.Static은 아래와 같이 접근 경로, 디렉토리(상대경로)로 설정되며

index.html은 연결되어도 디렉토리에 대해서 리스팅을 해주지 않는데

e := echo.New()
e.Static("/static", "assets")

 

e.Use에 middleware를 사용하고 Browse:true를 넣어주면

apache에서 처럼 index.html이 없는 디렉토리에서 목록을 리스팅해준다.

Root 는 static과 같이 입력하면 실행으로 부터 상대경로로, /static과 같이 입력하면 절대경로로 작동한다.

 

e := echo.New()
e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
  Root:   "static",
  Browse: true,
}))

[링크 : https://stackoverflow.com/questions/45558773/serving-files-with-echo]

[링크 : https://echo.labstack.com/middleware/static/]

 

테스트 디렉토리에 아래와 같이 파일을 생성하고

# cd test
# ls -al
total 32
drwxr-xr-x    2 root     root         16384 May  8 10:52 .
drwxr-xr-x    6 root     root         16384 May  8 10:52 ..
-rwxr-xr-x    1 root     root             0 May  8 10:52 1.log
-rwxr-xr-x    1 root     root             0 May  8 10:52 2.log

 

localhost/test 로 접속하면 이쁘진 않은데 아래와 같이 목록이 출력된다.

'Programming > golang' 카테고리의 다른 글

golang mutex (sync)  (0) 2023.05.16
go 포맷터  (0) 2023.05.11
golang websocket binary  (0) 2023.03.28
golang 크로스 컴파일 GOARM GOARCH  (0) 2023.02.03
golang map 에 데이터 추가하기  (0) 2023.01.13
Posted by 구차니

댓글을 달아 주세요

Programming/golang2023. 3. 28. 10:36

웹소켓을 통해 데이터를 JSON으로 변환해서 보내니 웹서버에 부하가 걸리는 것 같아서

binary 데이터 그대로~ 보내고 웹에서 binary를 처리하도록 하려고 찾아보는 중

 

서버 사이드(golang)

for {
    messageType, p, err := conn.ReadMessage()
    if err != nil {
        log.Println(err)
        return
    }
    if err := conn.WriteMessage(messageType, p); err != nil {
        log.Println(err)
        return
    }
}
In above snippet of code, p is a []byte and messageType is an int with value websocket.BinaryMessage or websocket.TextMessage.

[링크 : https://pkg.go.dev/github.com/gorilla/websocket#section-readme]

[링크 : https://kiwitrip.tistory.com/5]

 

클라이언트 사이드(웹 브라우저)

webSocket.onmessage = function (message) {
    var blob = message.data;
    var fileReader = new FileReader();
    fileReader.onload = function (event) {
        var arrayBuffer = event.target.result;
        var dataview = new DataView(arrayBuffer);
        var answer = dataview.getFloat64(0);
        alert("Server> : " + answer);
    };
    fileReader.readAsArrayBuffer(blob);
};

[링크 : http://www.gisdeveloper.co.kr/?p=5594]

 

+

23.04.04

var wsHost = "http://my-sites-url.com/path/to/echo-web-socket-handler";
var ws = new WebSocket(wsHost);
var buffer = new ArrayBuffer(5); // 5 byte buffer
var bufferView = new DataView(buffer);

bufferView.setFloat32(0, Math.PI);
bufferView.setUint8(4, 127);

ws.binaryType = 'arraybuffer';

ws.onmessage = function(message) {
    var view = new DataView(message.data);
    console.log('Uint8:', view.getUint8(4), 'Float32:', view.getFloat32(0))
};

ws.onopen = function() {
    ws.send(buffer);
};

[링크 : https://riptutorial.com/javascript/example/6661/working-with-binary-messages]

'Programming > golang' 카테고리의 다른 글

go 포맷터  (0) 2023.05.11
golang echo directory listing  (0) 2023.05.08
golang 크로스 컴파일 GOARM GOARCH  (0) 2023.02.03
golang map 에 데이터 추가하기  (0) 2023.01.13
golang reflect  (0) 2023.01.03
Posted by 구차니

댓글을 달아 주세요