Go는 2009년 구글에서 일하는 로버트 그리즈머, 롭 파이크, 켄 톰프슨이 개발한 프로그래밍 언어이다.
일단 Go는 속도가 매우 빠르다.
이처럼 Go는 Python처럼 간결한 문법 구조를 가지면서도 Python보다 훨씬 빠른 속도를 가져 많은 사람들에게 사랑받는 언어로 떠오르고 있다.
먼저 Go를 시작하기 위해서는 컴퓨터에 Go를 다운받아야 한다. 설치가 귀찮거나 개인 컴퓨터가 없다면 repl.it을 사용하는 것도 좋은 방법이다.
Go를 설치하면 C드라이브
혹은 /usr/local
에 go라는 폴더가 생기는데 Go프로젝트는 모두 go폴더에 있어야 한다.
만약 go폴더가 없다면 C드라이브 or /usr/local 에 go 라는 폴더를 만들고 go폴더 안에 bin pkg src폴더를 만들면 된다.
go 폴더를 찾았다면 src 폴더로 들어간 다음에 src폴더 안에 github.com이라는 폴더를 만들어준다. Go에는 npm이나 pip같은 것들이 없기 때문에 가져온 코드들은 모두 도메인 별로 분류를 해둔다. 나는 github를 사용하기 때문에 github.com이라는 폴더를 만든후 그 안에 자신의 유저명으로 폴더를 하나 만들면 Go프로젝트를 만들 준비는 모두 끝난것이다.
go를 설치했다면 이제 프로젝트를 생성해볼 시간이다. 먼저 자신의 유저명으로 되어있는 폴더로 들어가서 원하는 프로젝트명으로 폴더를 생성한다
Ex)
mkdir GoExample
폴더를 만들었다면 그 폴더 안으로 들어간 후에 main.go 파일을 생성한다.
파일을 컴파일 하고 싶다면 절대로 저 파일명을 바꿔서는 안된다.
main.go 파일을 만들었다면 이제 프로젝트를 시작할 준비는 끝났다. 먼저 Go가 잘 작동하는지 테스트 하기 위해서 아래 코드를 붙여넣어 보자.
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}
커맨드 창에 go run main.go
라고 쳤을때 Hello World!
라고 나온다면 go를 배울 모든 준비를 마친 것이다. 이 모든 과정이 복잡해 보이고 귀찮아 보인다면 처음에 말한것 처럼 그냥 repl.it을 사용하면 바로 go를 시작할 수 있다.
Go에는 package라는 것이 존재한다. go는 기본적으로 수많은 패키지들을 지원하며 위의 예제에서 보여준 fmt라는 패키지도 go에서 기본으로 제공하는 패키지이다. go가 지원하는 기본 패키지에 대해 더 알고 싶다면 여기로 들어가면 볼 수 있다.
go의 컴파일러는 main패키지를 특별하게 인식해 main package를 실행 프로그램으로 만들기 때문에 파일을 공유해서 사람들과 함께 사용하고 싶다면 패키지 이름을 main으로 하면 안된다.
먼저 go에서 함수를 만들고 싶다면 아래와 같이 적으면 된다.
func main() {
fmt.Println("Example code")
}
그리고 함수에 인자를 넘기거나 함수가 어떠한 값을 리턴해야 한다면 인자와 리턴값에 모두 타입을 명시해야한다. 타입을 명시하지 않는다면 go의 컴파일러가 에러를 내뿜는다.
go 에서 Function을 Export하고 싶다면 함수이름의 첫글자를 대문자로 하면 된다.
export const main = () => {}
Go 에서는 function을 대문자로 작성하기만 하면 function을 export할 수 있다.
func ThiswillExport() {
fmt.Println("This will export")
}
이러한 이유때문에 Go에서는 대문자로 시작하는 코드를 많이 볼 수 있다.
Go의 function에는 또 다른 차이점이 있는데 바로 defer이라는 것이다. defer은 함수가 종료되면 실행되는 함수이다.
func main() {
defer afterMain()
}
func afterMain() {
fmt.Println("This will be occur after main")
}
Go에서의 상수는 JS와 매우 유사하다. 상수를 사용하고 싶다면 아래와 같이 작성하면 된다.
const constant string = "Constant"
이처럼 JS와 매우 유사한 형식을 가지고 있지만 1가지 차이점은 직접 타입을 명시해야 한다는 것이다.
상수도 JS와 매우 유사하다시피 변수도 유사하다.
var something string = "Something"
하지만 이처럼 타입을 하나 하나 입력하게 하면 개발자들이 짜증이 난다는 것을 알고 있는 go의 개발자들은 우리를 위해 축약형을 만들어 줬다.
var something := "Something"
이런식으로 작성하면 Go의 컴파일러가 자동으로 타입을 찾아주기 때문에 개발자가 더욱 편하게 개발할 수 있다. (하지만 상수에서는 사용할 수 없다는 단점이....)
Go에서 루프는 for밖에 사용할 수 없다.(forEach, map, while 같은건 없다.)
for 초깃값;조건식;변화식 {
// () 를 사용하지 않는다
}
for 조건 {
//변화식
}
for {
// 무한루프
}
func main() {
// 0부터 10까지 출력
for i:=0;i<=10;i++{
fmt.Println(i)
}
}
슬라이스나 맵을 순회할 수 있음
에시
func main() {
var numbers = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
for _, i := range numbers{
fmt.Println(i)
}
}
Go는 함수들의 병렬실행을 지원한다. 그래서 미친듯이 빠른 속도를 낼 수 있는데 함수를 동시에 실행시키는 방법이 바로 Goroutines를 사용하는 것이다.
Goroutine을 사용하는 방법은 매우 간단하다. 그냥 사용하고 싶은 함수를 호출할때 앞에 go를 붙여주기만 하면 된다.
func main() {
go count("dave")
go count("justin")
time.Sleep(time.Second * 5)
}
func count(person string) {
for i:=0;i<10;i++{
fmt.Println(person, "is Good", i)
time.Sleep(time.Second)
}
}
밑에
time.Sleep(time.Second * 5)
을 붙여주는 이유는 함수 앞에 go 를 붙이면 main함수가 Goroutines을 기다려 주지 않는다 그래서 강제로 기다리게 하기 위해서 time.Sleep를 넣어주는 것이다.
Channels은 Goroutines <-> main 혹은 Goroutines <-> Goroutines 사이에서 정보를 전달하기 위한 방법이다.
먼저 Goroutine에서 main으로 정보를 보내고 싶다면 Channel을 만들어야 한다. Channel을 만들고 싶다면 아래와 같이 하면 된다.
channel := make(chan bool)
// 채널이름 := make(타입 리턴타입)
이렇게 만든 채널을 병렬로 실행하고 싶은 함수들에게 인자로 보내주고 인자로 채널을 받은 함수는 채널에 리턴값을 넣어주면 된다.
func main() {
channel := make(chan bool)
people := [2]string{"dave", "justin"}
for _, person := range people {
go isGood(person, channel)
}
result := <- channel
fmt.Println(result)
}
func isGood(person string, channel chan bool) {
channel <- true
}
channel안에 값을 넣고 싶으면 channelName <- value
를 하면 되고 값을 꺼내서 변수에 저장하고 싶다면 result := <- channelName
이런식으로 하면 된다.
채널을 사용하게 된다면 Goroutine만 사용할때 처럼 Sleep를 써줄 필요가 없다. main이 channel의 정보를 받을때까지 기다려 주기 때문이다.
이 글에서 소개하지 않은 if-else, switch, pointer등은 다른언어와 비슷한 부분이 많아서 제외했다.(조금씩 추가할 예정이다.)