GORM, Echo 웹 서버, gRPC 서버를 실행하고, GoLand에서 원격 디버깅을 진행하였다. 결론부터 말하면, GoLand는 원격 디버깅을 잘 지원한다.
1. GORM 원격 디버깅
GoLand를 사용해서 일반적인 Go 어플리케이션을 원격 디버깅하는 데모를 진행한다.
동일한 프로젝트로 생성, GOPATH 이하에 같은 폴더와 같은 소스명으로 구성한다.
build 시 옵션을 추가한다. go build -gcflags="all=-N -l" -o gorm
[root@localhost ~]# systemctl stop firewalld
[root@localhost gorm]# go get -u github.com/go-delve/delve/cmd/dlv
go: downloading github.com/go-delve/delve v1.8.0
go: downloading github.com/spf13/cobra v1.1.3
go: downloading github.com/spf13/cobra v1.3.0
go: downloading github.com/mattn/go-isatty v0.0.3
go: downloading github.com/konsorten/go-windows-terminal-sequences v1.0.3
go: downloading golang.org/x/sys v0.0.0-20211019181941-9d821ace8654
go: downloading golang.org/x/sys v0.0.0-20220111092808-5a964db01320
go: downloading github.com/cosiner/argv v0.1.0
go: downloading github.com/derekparker/trie v0.0.0-20200317170641-1fdf38b7b0e9
go: downloading github.com/mattn/go-colorable v0.0.9
go: downloading github.com/peterh/liner v1.2.1
go: downloading github.com/google/go-dap v0.6.0
go: downloading go.starlark.net v0.0.0-20200821142938-949cc6f4b097
go: downloading go.starlark.net v0.0.0-20211203141949-70c0e40ae128
go: downloading github.com/mattn/go-runewidth v0.0.3
go: downloading golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4
go: downloading github.com/mattn/go-runewidth v0.0.13
go: downloading golang.org/x/arch v0.0.0-20210923205945-b76863e36670
go: downloading github.com/cpuguy83/go-md2man v1.0.10
go: downloading github.com/cpuguy83/go-md2man/v2 v2.0.0
go: downloading github.com/cpuguy83/go-md2man/v2 v2.0.1
go: downloading github.com/cilium/ebpf v0.7.0
go: downloading github.com/russross/blackfriday/v2 v2.0.1
go: downloading github.com/russross/blackfriday v1.6.0
go: downloading github.com/russross/blackfriday/v2 v2.1.0
go: downloading github.com/shurcooL/sanitized_anchor_name v1.0.0
go: downloading github.com/rivo/uniseg v0.2.0
go get: added github.com/cpuguy83/go-md2man v1.0.10
go get: added github.com/go-delve/delve v1.8.0
go get: added github.com/mattn/go-runewidth v0.0.13
go get: added github.com/sirupsen/logrus v1.8.1
go get: added github.com/spf13/cobra v1.3.0
go get: added go.starlark.net v0.0.0-20211203141949-70c0e40ae128
go get: added golang.org/x/arch v0.0.0-20210923205945-b76863e36670
go get: upgraded golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd => v0.0.0-20220111092808-5a964db01320
[root@localhost gorm]#
dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec ./gorm
192.168.17.206 입력
자동 생성된 Debug 'go build gorm' 을 선택
API server listening at: 127.0.0.1:59750 출력한다. build -gcflags="all=-N -l" 옵션이 추가되면 API server listening 출력이 사라진다.
GOROOT=C:\Program Files\Go #gosetup
GOPATH=C:\Users\germany\go #gosetup
"C:\Program Files\Go\bin\go.exe" build -o C:\Users\germany\AppData\Local\Temp\GoLand\___go_build_gorm.exe -gcflags "all=-N -l" gorm #gosetup
"C:\Program Files\JetBrains\GoLand 2021.3.2\plugins\go\lib\dlv\windows\dlv.exe" --listen=127.0.0.1:59954 --headless=true --api-version=2 --check-go-version=false --only-same-user=false exec C:\Users\germany\AppData\Local\Temp\GoLand\___go_build_gorm.exe --
API server listening at: 127.0.0.1:59954
브레이크포인트에서 중지
2. Echo 원격 디버깅
옵션을 추가해서 빌드한다.
go build -gcflags="all=-N -l" -o echo
아래처럼 dlv를 시작한다.
dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec ./echo
C:\Users\germany\go\echo>go build -gcflags="all=-N -l" -o echo.exe
3. gRPC
처음에 사용하던 예제 소스를 변경했다. 아래의 작업은 GoLand가 설치된 VM에서 진행한다.
syntax = "proto3";
option go_package = "google.golang.org/grpc/examples/helloworld/main";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
package main;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
PATH=$PATH:/root/Downloads/bin
C:\Users\germany\go\grpc>protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld.proto
'protoc-gen-go' is not recognized as an internal or external command,
operable program or batch file.
--go_out: protoc-gen-go: Plugin failed with status code 1.
설치해 주지 않으면 위의 에러가 발생한다.
C:\Users\germany\go\grpc>go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
go: downloading google.golang.org/protobuf v1.26.0
C:\Users\germany\go\grpc>go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
go: downloading google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0
go: downloading google.golang.org/protobuf v1.23.0
package main
import (
"context"
"flag"
"fmt"
"log"
"net"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
var (
port = flag.Int("port", 50051, "The server port")
)
// server is used to implement helloworld.GreeterServer.
type server struct {
pb.UnimplementedGreeterServer
}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
func main() {
flag.Parse()
lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
C:\Users\germany\go\grpc>go mod init main
C:\Users\germany\go\grpc>go mod tidy
C:\Users\germany\go\grpc>go build -gcflags="all=-N -l" -o main
main.exe로 빌드하지 않아도 문제가 없다. 브레이크 포인트가 문제 없이 적용된다.
동일한 작업을 서버에서도 진행한다. 특이사항은 없다.
https://github.com/protocolbuffers/protobuf/releases 에서 protoc-3.19.3-linux-x86_64.zip을 다운받는다.
PATH에 추가한다.
PATH=$PATH:/root/Downloads/bin
dlv를 시작한다.
[root@localhost grpc]# dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec ./main
API server listening at: [::]:2345
2022-01-11T21:14:21-05:00 warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)