본문 바로가기

코딩 및 기타/프로젝트

GO 프로그래밍

728x90

∙ 예제로 배우는 GO 프로그래밍

∙Golang 특징

1. 전통적인 컴파일, 링크 모델을 따르는 범용 프로그래밍 언어

2. 정적 타입의 언어, Garbage Collection 기능 제공

3. Communicating Sequential Processes(CSP) 스타일의 Concurrent 프로그래밍을 지원

 

* CSP : 순차 프로세스 통신

 

∙ Hello World 프로그램

- 기본적으로 프로젝트마다 새로운 작업 폴더를 만들어 사용할 수 있다. 작업폴더는 일반적으로 bin, pkg, src라는 3개의 폴더를 생성하고, 소스코드는 src 폴더 밑에 둔다.

GO는 main 패키지 내의 Entry Point인 main() 함수를 찾아 프로그램을 실행한다.

 

∙ 변수

- 변수는 GO 키워드 var 를 사용하여 선언한다.

- 선언된 변수가 GO 프로그램 내에서 사용되지 않는다면 에러를 발생시킨다. (사용하지않는 변수는 삭제를 해야함)

ex) var a int 

ex) var f float32 = 11. 1

- 초기값을 지정하지 않으면 Zero Value를 기본적으로 할당된다. (숫자형은 0, bool 타입은 false, string형은 ""(빈문자열)을 할당)

ex) var i, j, k int = 1, 2, 3 

package main

func main() {
	var a int
	println(a)
	// 실수형은 이상헤 나옴,,,,
	var f float64 = 11.
	println(f)
	a = 10
	f = 12.0
	println(a)
	println(f)

	// 복수 변수들이 선언된 상황에서 초기값을 지정할 수 있음
	var i, j, k int = 1, 2, 3
	println(i, j, k)

	// 할당되는 값을 보고 그 타입을 추론하는 기능이 있음
	var q = 1
	var s = "Hi"
	println(q)
	println(s)
}

 

∙ 상수

- GO 키워드 const를 사용하여 선언한다.

package main

func main()
{
	const c int = 10
	const s string = "Hi"

	// 할당되는 값을 보고 그 타입을 추론하는 기능
	const a = 20
	const st = "const Hi"

	// 여러 개의 상수들을 묶어서 지정할 수 있음
	const(
		Visa = "Visa"
		Master = "Master"
		Amex = "American Express"
	)

	// iota을 지정하는 경우 iota이 지정된 변수는 0이 할당되고,
	// 나머지는 순서대로 1씩 증가된 값을 부여 받음
	const(
		Apple = iota    // 0
		Grape			// 1
		Orange			// 2
	)

}

 

∙ 데이터 타입

- 기본적인 타입 + 기타 타입

- 기타 타입 : byte -> uint8과 동일하며 바이트 코드에 사용, rune -> int32과 동일하며 유니코드 코드포인트에 사용

 

- 데이터 타입 변환

ex) 정수 100을 float로 변경하기 위하여 float32(100)으로 수정, 문자열 바이트로 변결하기 위하여 []byte("ABC")로 수정

package main

func main() {
	var i int = 100
	var u uint = uint(i)
	var f float32 = float32(i)
	println(u, f)

	var str = "ABC"
	var bytes = []byte(str)
	var str2 = string(bytes)
	println(bytes, str2)
}

 

∙ 연산자

- 산술연산자

사칙연산자와 증감연산자를 사용

 

- 관계연산자

서로의 크기를 비교하거나 동일함을 체크하는데 사용

 

- 논리연산자

AND, OR, NOT을 표현하는데 사용

 

- Bitwise연산자

비트단위 연산을 위해 사용되는데, 바이너리 AND, OR, XOR와 바이너리 쉬프트 연산자가 있음

 

- 포인터연산자

C++와 같이 & 혹은 * 을 사용하여 해당 변수의 주소를 얻어내거나 이를 반대로 Dereference 할 때 사용

 

∙ 반복문

package main

func main() {
	// 기본 for 루프
	var sum = 0
	for i := 1; i <= 100; i++ {
		sum += i
	}
	println(sum)

	// 조건식만 쓰는 for 루프
	var n = 1
	for n < 100 {
		n *= 2
	}
	println(n)

	// 무한루프
	for{
		println("Infinite loop")
	}
}

 

- for range 문

컬렉션으로 부터 한 요소(element)씩 가져와 차례로 for 블럭의 문장들을 실행

"for 인덱스,요소값 := range 컬렉션" 같이 for 루프를 구성, 그 요소의 위치인덱스와 값을 for키워드 다음의 2개의 변수에 각각 할당

package main

func main() {
	var names = []string{"홍길동", "이순신", "강감찬"}

	for index, name := range names {
		println(index, name)
		// 0 홍길동
		// 1 이순신
		// 2 강감찬 
	}
}

 

∙ 함수

여러 문정울 묶어서 실행하는 코드 블럭의 단위, func 키워드를 사용하여 정의 

package main

// pass by value
func main() {
	var msg = "Hello"
	say(msg)
}

// 함수 생성 
func say(msg string) {
	println(msg)
}

// pass by reference
func main() {
	var msg = "Hello"
	say(&msg)
	println(msg) // 변경된 메시지 출력
}

func say(msg *string) {
	println(*msg) // 요청 받은 메시지 출력
	*msg = "Changed"
}

// variadic function(가변인자함수)
func main(){
	say("This", "is", "a", "book")
	say("Hi")
}
// 함수에 고정된 수의 파라미터들을 전달하지 않고 다영한 숫자의 파라미터를 전달하고나 할 때
// 거뵨 파라미터를 나타내는 ... 을 사용
func say(msg ...string){	
	for _, s := range msg{
		println(s)
	}
}

 

- 익명함수

함수명을 갖지 않는 함수를 익명함수이라 부름, 일반적으로 그 함수 전체를 변수레 할당하거나 다른 함수의 파라미터에 직접 정의되어 사용함

package main

func main() {
	// 익명함수 정의
	var sum = func(n ...int) int {
		s := 0
		for _, i := range n {
			s += i
		}
		return s
	}

	result := sum(1, 2, 3, 4, 5) // 익명함수 호출
	println(result)
}

 

∙ 배열

package main

func main() {
	// 3개의 배열 생성
	var a [3]int
	a[0] = 1
	a[1] = 2

	//배열크기 자동으로 할당
	var b = [...]int{1, 2, 3}
	println(b[2])

	// 다차원 배열
	var arr = [2][3]int{
		{1, 2, 3},
		{4, 5, 6}, // 끝에 콤마 추가
	}
	println(arr[1][2])

	/* [...] 다차원 배열은 불가능
	var arr1 = [...][...]int{
		{1, 2, 3},
		{4, 5, 6},
	}
	println(arr1[1][2])
	*/
}

 

∙ 슬라이스(Slice)

배열과 달리 고정된 크기를 미리 지정하지 않을 수 있고, 차후 그 크기를 동적으로 변경할 수 도 있고 또한 부분 배병을 발췌할 수 있음

package main

// fmt 패키지는 포맷 템플릿이다.
import "fmt"

func main() {
	var a []int        //슬라이스 변수 선언
	a = []int{1, 2, 3} // 슬라이스에 리터럴값 지정
	a[1] = 10
	println(a) // 3/3]0x14000014120 이 출력됨
	fmt.Println(a) // [1 10 3] 이 출력됨
}

Slice를 생성하는 또 다른 방법으로 Go의 내장함수 make() 함수를 이용할 수 있다.(슬라이스의 길이와 용량을 임의로 지정할 수 있음)

별도의 길이와 용량을 지정하지 않으면, 기본적으로 길이와 용량이 0인 슬라이스를 만드는데 이를 Nill Slice라고 하고, nil과 비교하면 참을 리턴한다

func main(){
	s := make([]int, 5, 10)
	s[0] = 1
	s[1] = 2
	s[2] = 3
	s[3] = 4
	s[4] = 5
	println(len(s), cap(s)) // 5, 10
	fmt.Println(s)
}

 

∙ Map

키(key)에 대응하는 값(value)을 신속히 찾는 해시테이블을 구현한 자료구조이다.

package main

import "fmt"

func main() {
	// map 선언
	var idMap map[int]string
	// 초기화
	idMap = make(map[int]string)
	idMap[901] = "Apple"
	idMap[801] = " Grape"

	// 키에 대한 값 읽기
	str := idMap[901]
	println(str)
	// 삭제
	delete(idMap, 901)

	noData := idMap[901]
	println(noData) // 값이 없으면 nill 혹은 zero리턴

	// 리터럴을 사용한 초기화
	tickers := map[string]string{
		"GOOG": "Google Inc",
		"MSFT": "Microsoft",
		"FB":   "FaceBook",
	}
	str1 := tickers["GOOG"]
	println(str1)

	// map 키 체크
	val, exists := tickers["MSFT"]
	if !exists {
		println("No MSFT ticker")
	}

	// for 루프를 사용한 Map 열거
	myMap := map[string]string{
		"A": "Apple",
		"B": "Banana",
		"C": "Charlie",
	}
	for key, val := range myMap {
		fmt.Println(key, val)
	}
}

 

∙ 구조체

GO에서 struct는 Custom Data Type을 표현하는데 사용되고, 필드들의 집합체이며 필드들의 컨테이너이다.

Go에서 struct는 필드 데이터만을 가지며, 메서드를 갖지 않는다.

package main

import "fmt"

// struct 정의
type person struct {
	name string
	age  int
}

func main() {
	// 객체 생성
	p := person{}
	// 필드값 설정
	p.name = "Lee"
	p.age = 10

	var p1 person
	p1 = person{"Bob", 20}
	p2 := person{name: "Sean", age: 50}
	fmt.Println(p)
	fmt.Println(p1, p2)
}

 

'코딩 및 기타 > 프로젝트' 카테고리의 다른 글

OpenAI 사용방법  (0) 2023.10.21
MDM  (0) 2023.10.20
Agentless(MDM)  (0) 2023.10.15
Sliver(슬리버)  (0) 2023.10.07
HAVOC  (0) 2023.10.03