Go
return
client, err := net.DialTimeout(netScheme, host, time.Duration(w.Timeout))
if err != nil {
fmt.Printf("Error: %v\n", err)
} else {
fmt.Printf("Connected to %v\n", client.RemoteAddr())
}
자바로 치면,
// Java에서 다중 반환 값을 처리하는 예시
// 사용자 정의 클래스
class ConnectionResult {
public Socket client;
public Exception error;
public ConnectionResult(Socket client, Exception error) {
this.client = client;
this.error = error;
}
}
public ConnectionResult connect(String host, int timeout) {
try {
Socket client = new Socket();
client.connect(new InetSocketAddress(host, timeout));
return new ConnectionResult(client, null);
} catch (IOException e) {
return new ConnectionResult(null, e);
}
}
// 사용 예시
ConnectionResult result = connect("example.com", 1000);
if (result.error != null) {
System.out.println("Error: " + result.error.getMessage());
} else {
System.out.println("Connected to " + result.client.getRemoteSocketAddress());
}
for loop
go
-
_
언더바부분에서 인덱스를 받을 수 있다. - 언더바 넣은건 인덱스 무시한다는 뜻
-
:=
는 변수 할당한다는 뜻
// w.hosts 슬라이스가 있다고 가정
for _, host := range w.hosts {
// 여기서 host 변수는 w.hosts의 현재 요소입니다.
fmt.Println("Connecting to:", host)
}
java
- 반면 자바에서는 for-each 에서 인덱스에 접근할순 없음
// hosts 리스트가 있다고 가정
List<String> hosts = Arrays.asList("host1", "host2", "host3");
for (String host : hosts) {
// 여기서 host 변수는 hosts 리스트의 현재 요소입니다.
System.out.println("Connecting to: " + host);
}
Go 튜토리얼
Getting Started
- root에 go.mod 필요
- module 에는 주로 코드 주소 예를 들어 깃헙 리포지토리면 github/example
- go mod init github/example
- 종속성 관리
- 중앙 저장소는 어디?
- Go Proxy
- proxy.golang.org
- 공개된 중앙 저장소
- 다운로드된 모듈은 $GOPATH/pkg/mod
- 접근가능한 URL도 가능
import "github.com/user/repo/package"
Create a Go module
// 변수 선언 and 초기화 방법1
var message string
message = fmt.Sprintf("Hi, %v. Welcome!", name)
// 변수 선언 and 초기화 방법2
message := fmt.Sprintf("Hi, %v. Welcome!", name)
Call your code from another module
<home>/
|-- greetings/ (호출받는 패키지)
|-- hello/ (호출하는 패키지)
- 어떻게 호출 가능?
"example.com/greetings"
- production 환경이라면 배포된 그 리포지토리에 가져올것이지만, 로컬이니까 따로 지정을 해줘야한다
go mod edit -replace example.com/greetings=../greetings
명령어 사용하면 아래와같이 go.mod에 추가됨
module example.com/hello
go 1.22.5
replace example.com/greetings = >../greetings
-
go mod tidy
명령어로 실제로../greetings
를 바라볼수있게 동기화
Return and handle an error
- Go는 리턴값 2개이상 가능
- 에러 다룰때는
"errors"
사용
질문: name에 nil 넣으면 어떻게 되나요? 답변: Go 언어에서 string 타입은 기본적으로 nil이 아닌 빈 문자열 ""로 초기화됩니다. 즉, string 타입 변수는 nil 값을 가질 수 없으며, 초기화되지 않은 상태에서는 빈 문자열로 간주됩니다.
질문: string말고 어떤 타입이있고 어떤 기본값을 같나? 모두 nil 을 가질수없나? 답변: 타입에는 기본타입과 기본타입이 있다
아래꺼는 다른 문서로..
1. 기본 타입
• bool: 기본값은 false
• string: 기본값은 "" (빈 문자열)
• 정수 타입: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr: 기본값은 0
• 부동 소수점 타입: float32, float64: 기본값은 0.0
• 복소수 타입: complex64, complex128: 기본값은 0+0i
2. 기타 타입
• 배열: 모든 요소가 타입의 기본값으로 초기화된 배열
• 슬라이스: nil
• 맵: nil
• 포인터: nil
• 채널: nil
• 함수: nil
• 인터페이스: nil
• 구조체: 모든 필드가 타입의 기본값으로 초기화된 구조체
package main
import "fmt"
func main() {
var b bool
var s string
var i int
var f float64
var c complex128
var a [3]int
var p *int
var sl []int
var m map[string]int
var ch chan int
var fn func() int
var iface interface{}
fmt.Printf("bool: %v\n", b)
fmt.Printf("string: %v\n", s)
fmt.Printf("int: %v\n", i)
fmt.Printf("float64: %v\n", f)
fmt.Printf("complex128: %v\n", c)
fmt.Printf("array: %v\n", a)
fmt.Printf("pointer: %v\n", p)
fmt.Printf("slice: %v\n", sl)
fmt.Printf("map: %v\n", m)
fmt.Printf("channel: %v\n", ch)
fmt.Printf("function: %v\n", fn)
fmt.Printf("interface: %v\n", iface)
}
bool: false
string:
int: 0
float64: 0
complex128: (0+0i)
array: [0 0 0]
pointer: <nil>
slice: []
map: map[]
channel: <nil>
function: <nil>
interface: <nil>
Return a random greeting
목적
- 미리 정의한 여러 인사들중에 하나 리턴해보기
- 멀티파트 튜토리얼 시작하기 전에 한 부분으로 이해하기
변수, 함수, 타입의 이름
- 첫글자가 대문자이면 외부 패키지에서도 접근 가능한 공개(exported) 멤버가 됨
- 소문자이면, 패키지 내부에서만 접근가능한 비공개(unexported) 멤버가 됨
- 외부 패키지에서는 접근 가능하지 않은데, 같은 패키지 다른 go 파일에서는 randomFormat()에 접근 가능
슬라이스와 배열
var arr [3]int // 크기가 3인 int 배열 선언
arr = [3]int{1, 2, 3} // 배열 초기화
fmt.Println(arr) // 출력: [1 2 3]
s := []int{1, 2, 3} // int 슬라이스 선언 및 초기화
s = append(s, 4) // 슬라이스에 요소 추가
fmt.Println(s) // 출력: [1 2 3 4]
Return greetings for multiple people
목표
- 인사 map 리턴
질문: Go 언어에서 make() 뭐지?
messages := make(map[string]string)
// 맵 초기화
messages := make(map[string]string)
// 슬라이스 초기화
numbers := make([]int, 5) // 길이가 5인 슬라이스 생성
numbers := make([]int, 5, 10) // 길이가 5이고 용량이 10인 슬라이스 생성
// 채널 생성 (채널은 데이터 송수신 담당)
ch := make(chan int)
Add a test
- 파일 이름은 테스트할 파일 뒤에
_test
붙인다 -
"testing"
import 한다. - 에러 조건에 t.Fatalf() 쓴다
Go tcp client 코드 예제
func SendCloudWatch(cloudwatch model.AwsRdsCloudWatch) {
// ... 생략
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%s", host, portStr))
if err != nil {
logger.Error("Failed to connect to TCP server:", err)
return
}
defer conn.Close()
if err := send(conn, data.ToByteArray()); err != nil {
logger.Error("Failed to send data:", err)
}
}
func send(conn net.Conn, data []byte) error {
const writeTimeout = 5 * time.Second
totalBytesSent := 0
for totalBytesSent < len(data) {
writeDeadline := time.Now().Add(writeTimeout)
if err := conn.SetWriteDeadline(writeDeadline); err != nil {
return fmt.Errorf("failed to set write deadline: %v", err)
}
bytesSent, err := conn.Write(data[totalBytesSent:])
if err != nil {
return fmt.Errorf("failed to send data: %v", err)
}
totalBytesSent += bytesSent
}
return nil
}
defer
Go의 defer
- 목적: 함수가 종료될 때 실행할 작업을 예약하여 자원 해제 및 정리 작업을 보장.
- 영어 의미: 미루다, 연기하다 (=put off)
-
작동 방식:
- 예약 시점:
defer
가 호출되면 해당 함수가 종료될 때 실행할 함수를 스택에 푸시(push). - 실행 시점: 예약된 함수는 예약된 순서의 역순(후입선출, LIFO)으로 실행됨.
- 예약 시점:
-
사용 예:
- 파일 열기 및 닫기:
file, err := os.Open("example.txt") if err != nil { // 오류 처리 } defer file.Close() // 파일 닫기를 예약 // 파일 작업 수행
- 네트워크 연결:
conn, err := net.Dial("tcp", "example.com:80") if err != nil { // 오류 처리 } defer conn.Close() // 연결 닫기를 예약 // 네트워크 작업 수행
- 리소스 해제 보장: 함수 중간에 오류가 발생하더라도 함수가 종료될 때 예약된 작업이 실행됨.
- 파일 열기 및 닫기:
-
특징:
- 여러
defer
사용 시, 예약된 순서의 역순으로 실행됨:defer fmt.Println("First") defer fmt.Println("Second") defer fmt.Println("Third") // 출력: Third, Second, First (함수 종료 시)
- 여러
자바랑 비교
-
예약과 실행 시점:
- Go의
defer
: 함수 종료 시 예약된 작업을 역순으로 실행. - Java의
try-with-resources
:try
블록이 종료되거나 예외가 발생할 때 자원을 자동으로 닫음.
- Go의
-
사용 편의성:
- Go의
defer
: 간단한 구문으로 다양한 작업을 예약 가능. - Java의
try-with-resources
:AutoCloseable
인터페이스를 구현한 자원만 자동 닫기 가능.
- Go의
-
에러 처리:
- Go:
defer
를 통해 예외가 발생하더라도 자원 해제를 보장. - Java:
try-with-resources
를 통해 예외가 발생하더라도 자원을 자동으로 닫음.
- Go:
예제
-
Go 예제:
package main import ( "fmt" "os" ) func main() { file, err := os.Open("example.txt") if err != nil { fmt.Println("Error:", err) return } defer file.Close() // 파일 닫기를 예약 // 파일 작업 수행 }
-
Java 예제:
import java.io.FileInputStream; import java.io.IOException; public class Main { public static void main(String[] args) { try (FileInputStream file = new FileInputStream("example.txt")) { // 파일 작업 수행 } catch (IOException e) { System.out.println("Error: " + e.getMessage()); } // try 블록을 벗어나면 file이 자동으로 닫힘 } }
명령어
cd path/to/go-project
# Go 바이너리를 Amazon Linux 2023 및 ARM64용으로 빌드
GOOS=linux GOARCH=arm64 go build -o bootstrap main.go
# 실행 권한을 추가
chmod +x bootstrap
# 실행 파일을 압축
zip function.zip bootstrap
GOOS=linux GOARCH=amd64 go build -o main .