이 블로그 검색

레이블이 golang인 게시물을 표시합니다. 모든 게시물 표시
레이블이 golang인 게시물을 표시합니다. 모든 게시물 표시

2022년 3월 24일 목요일

golang 1.18의 workspace mode 알아보기

이번에 1.18 버전이 나오면서 크게 변경된 것 (generic, fuzzing, 성능 향상, workspace 모드) 중에서 나에겐 workspace 의 유용함이 가장 먼저 다가왔다. 

실제 프로젝트에서 golang 으로 개발하는 경우에 아주 유용한 기능이라고 생각된다. 

workspace 는 개발자가 동시에 여러 모듈들을 생성/수정 하면서 개발하는 경우 유용하게 사용될 기능이다.

예를 들자면, 어떤 모듈A 를 수정해야 하는데 , A모듈이 사용 중인 모듈B 도 같이 동시에 수정이 필요한 경우를 가정해보자.

개발 시 분명히 마주치게 될 이런 문제를 1.18 버전 이전에는 어떻게 해결했냐 하면, 

A모듈의 go.mod 파일에서 replace 지시자를 사용해서, B모듈의 경로를, 지금 수정하는 로컬 위치로 변경 해줘야만 했다. 

(이전글 참조 : golang module 작성, 타 모듈에서 로컬 테스트 및 배포 개념 정리)

로컬 경로는 개발자마다 전부 다를 것이므로, 소스 관리 차원에서도 함부로 replace 지시자 가 들어간 go.mod 파일을 소스 repo 에 commit,push 할 수 없었다. 한마디로 매우 성가시고 불편했다.

만약 replace 사용 없이 하려면 각각의 모듈 별로 개별 test 코드를 만들어서 독립적으로 완벽히 테스트 하면서 개발 후, 동시에 repo에 발행한다며, 아마도 어쩌면? 가능 했을지도 모른다. 

하지만 개발자는 신이 아니기에, 이런 식으로 개발 할 수는 없을 듯 하다. A 를 수정하다 보면 B 도 수정 필요하고 또 그 반대의 경우도 수시로 발생 될 수 있기 때문이다.

그런데 이제 workspace 를 사용하면 훨씬 편한 개발이 가능해졌다. go.work 파일이 존재하면 workspace mode로 동작하게 된다. 

그럼 이전 글에서 설명된 예제를 workspace 를 사용하는 것으로 수정을 해본다.

 

2022년 1월 2일 일요일

GOSOF : A simple yet quite practical socket framework made with golang.

 

https://github.com/jeremyko/gosof


Instead of the simple socket echo example that comes up a lot if you search, I tried to implement it so that it can properly handle the buffering of tcp data that can be split into pieces or transmitted all at once. And to increase reusability, I implemented it so that it can be used like a framework.

  • The framework calls the user-specified callback.
  • For TCP, the total size of user data is passed to the framework via a callback, and the framework does TCP buffering automatically.
  • Byte data is exchanged.
  • Supports TCP, UDP and Domain Socket.


When sending a byte message composed of a fixed-length header and variable-length body data, it may be useful as it can reduce the work a little.

udp and domain socket are also supported, but this is not much different from using the existing net package as it is, so there is no special point.

 

golang 으로 만든 간단하면서도 꽤 실용적인 socket 프레임워크.

검색하면 많이 나오는 단순한 socket echo 예제 대신, 조각으로 쪼개지거나, 한번에 다 전송될수 있는 tcp 의 데이터 버퍼링 처리를 제대로 처리 할 수 있게 끔 구현해 봤다. 그리고 재활용성을 높이기 위해 프레임워크 처럼 사용할수 있게 구현 해 봤다. 몇가지 특징을 나열하면,

  • 프레임워크가 사용자 지정 콜백을 호출한다.
  • TCP의 경우 사용자 데이터의 전체 크기는 콜백을 통해 프레임워크에 전달되고 프레임워크는 TCP 버퍼링을 자동으로 수행 해준다.
  • 바이트 데이터를 주고 받는다
  • TCP, UDP 및 도메인 소켓을 지원


고정길이 헤더와 가변길이 body 데이터로 구성된 byte 메시지를 전송할때 조금이나마 작업을 줄일수 있어서, 나름 유용할거 같다.

udp 나 domain socket 도 지원하지만, 이건 뭐 기존 net package 를 그대로 사용하는것과 거의 차이가 없기 때문에 별다른 점은 없겠다. 

https://github.com/jeremyko/ASockLib 과 비슷한 사용법을 가지고 있다.



2021년 8월 6일 금요일

golang : interface 로 전달받은 pointer 가 가르키는 type 을 찾기

reflect.Indirect 를 활용하면, interface 로 전달된 인자가 pointer인 경우, 그 pointer가 가르키는 실제 type 에 대한 정보를 알수 있다. 여러 type을 전달받는 공통 함수 등을 작성할때 유용한 tip

package main

import (
    "fmt"
    "reflect"
)

func testFunc(value interface{}) {
    fmt.Println("---------------------")
    fmt.Println("type = " + reflect.ValueOf(value).Type().String())
    fmt.Println("kind = " + reflect.ValueOf(value).Kind().String())
    if reflect.ValueOf(value).Kind()==reflect.Ptr {
	fmt.Println("--> pointer " )
	pointsToValue := reflect.Indirect( reflect.ValueOf(value))
	fmt.Println("-->",pointsToValue.Kind(), 
	    " - ",pointsToValue.Type(), " - ", pointsToValue)
	if pointsToValue.Kind()==reflect.Slice {
	    fmt.Println("--> slice !! " )
        }
    }
}

func main() {
    var testVar1 string
    var testVar2 []string
    var testVar3 []*string 
    
    testVar2 = append(testVar2,"A")
    testVar2 = append(testVar2,"B"
 
    testFunc(testVar1)
    testFunc(&testVar1)
    testFunc(testVar2)
    testFunc(&testVar2)
    testFunc(testVar3)
    testFunc(&testVar3)
}

 

https://play.golang.org/p/1PEOYIPdyFb


2021년 4월 27일 화요일

Go 1.16 에서 $GOPATH/src 에서 코드 작성하고 사용하기

Go 1.16 버전 부터는 기본적으로 module 을 사용하게 변경 되었다. 덕분에 GOPATH  와 상관없이 아무 위치에서든 자신의 소스파일을 작성하면 된다.  그리고 모듈을 사용하기 위한 go.mod 파일이 반드시 필요하게 되었다.  하지만 1.16 버전에서도 선택적으로 module 사용을 할지 말지 여부를 결정 할 수 있다. 예를 들어 기존 프로젝트 구조가 GOPATH 내 src 를 사용하는 경우등이 해당될수 있다.

2021년 4월 25일 일요일

go module과 package 관계, 그리고 module path 개념 정리

go 의 기본적인 개념 중에서 모듈, package 그리고 모듈 경로에 대해 알아본다. 처음에 개인적으로 많이 헷갈렸던 부분이라서 정리해 본다. 지금 우리가 go 로 어떤 프로젝트를 수행한다고 가정해 보면, 다음처럼 정리 할 수 있겠다. 

  • 이 프로젝트는 여러개의 모듈을 가질수 있다.
  • 각 모듈에는 여러개의 package들이 존재할수 있다.
  • 각 package 들은 1개 이상의 go 소스파일로 구성된다.
  • 모듈내의 각 package 들은 자신의 package 폴더를 go mod init 으로 지정한 모듈 경로 + 폴더로 만들면 된다. 
  • 패키지명은 (반드시) 경로의 마지막 문자열로 해준다.
  • 개발중인 모듈은 반드시 원격 저장소에 배포될 필요가 없다.
  • 로컬 개발환경에서 동시에 여러 모듈을 개발중이고, A모듈이 B모듈을 사용해야 한다면, B모듈의 경로를 개발 중인 로컬 경로로 변경하는 작업이 필요하다.(이건 예전 상황이고.. go 1.18 부터는 그냥 workspace 를 사용하면 됨)

위 내용들을 하나씩 살펴보자. (go 1.16 기준으로 작성됨)

2021년 4월 24일 토요일

go 에서 gRPC-Gateway 사용하기

이번에는 go 에서 gRPC-Gateway 를 사용하는 방법에 대해 알아보려 한다. 

최종 코드는 다음에서 확인 가능 : https://github.com/jeremyko/grpc-gateway-sample

앞서 살펴본 go 에서 proto buffer 사용하기 와 거의 비슷한 절차이나 gRPC-Gateway 사용을 위해 추가되는 절차가 있다. 다음 내용을 기초로 작성되었다 (그대로 따라 했더니 에러가 발생되어, 최신 go 버전에 맞게 내용이 추가된 부분이 있다. go 1.16 버전 기준).

https://grpc-ecosystem.github.io/grpc-gateway/docs/tutorials/introduction/

필요한 패키지 다운로드

go get google.golang.org/grpc
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go get google.golang.org/protobuf/cmd/protoc-gen-go
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc

2021년 4월 22일 목요일

go 에서 proto buffer 사용하기

1. proto buffer 를 정의
2. go 로 변환하여 모듈을 만들고
3. 이 모듈을 로컬에서 호출해서 사용 하는 간단한 예제를 정리해 본다 (go 1.16 버전을 기준)

최종 코드는 다음을 참고 : https://github.com/jeremyko/go-proto-buffer-sample

2021년 3월 19일 금요일

golang module 작성, 타 모듈에서 로컬 테스트 및 배포 개념 정리

2022-03-24 update

go 1.18부터 도입된 workspace 기능을 사용하면 mod replace 를 대체 가능하다 

https://jeremyko.blogspot.com/2022/03/golang-118-workspace-mode.html

 

 

golang 모듈을 만들고 타 모듈에서 사용하는 것을 한번 정리해보았다.
내가 만들려고 하는 모듈이
github.com/jeremyko/my_mod 이며, 모듈 폴더는 ~/mydev/my_mod 라고 가정한다.