ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • golang package 이해하기
    Language/Golang 2023. 9. 18. 23:36
    728x90
    반응형

     

    - 목차

     

    * 소개

    go 프로젝트에서 package를 어떻게 구성해야할까요 ?
    go 의 package convention 과 directory - package 의 관계에 대해서 알아보도록 하겠습니다.
     

    * main package

    대부분의 프로그래밍 언어는 main 함수를 가집니다.
    main 함수와 그 함수를 가지는 파일은 컴파일러에게 특별하게 인식이 되는데요.
    컴파일러는 main 함수를 가지는 파일을 실행파일로 인식하고
    main 함수가 실행파일의 entrypoint 가 됩니다.
     
    예를 들어,
    java 에서 public static void main () {} 형식으로 main method 가 선언된 클래스는 Main Class 라고 부르며
    main method 를 가지는 클래스는 자바 컴파일러에 의해서 entrypoint 로 인식됩니다.
     
    python 에서도 if __name__ == "__main__" {} 과 같이 entrypoint 로 사용된 파이썬 스크립트를 식별할 수 있습니다.
    ( python main.py 로 실행된 main.py 스크립트 파일의 __name__ 변수값이 "__main__" 로 세팅됨. )
     
    이처럼 go 에서도 main 함수가 등록된 go file 과 go package 를 실행 파일, 실행 패키지로 인식합니다.
     
    예를 들어보겠습니다.
     
    프로젝트의 directory 구조는 아래와 같습니다.
    project 라는 이름의 project 폴더 바로 밑에 go.mod 와 main.go 가 있습니다.
     

    /project
    	/go.mod
    	/main.go

     
    <main.go>

    package main
    
    import "fmt"
    
    func main() {
    	fmt.Print("hi")
    }

     

    project 폴더 밑에 main2.go 라는 이름의 파일을 생성해보겠습니다.

    /project
    	/go.mod
    	/main.go
    	/main2.go

     

    <main2.go>

    package main
    
    func main() {
    	print("hi")
    }

     
    이때 package main 과 func main () 를 추가했는데요.
    아래 사진처럼 main 패키지는 사용할 수 없습니다. (package main 에 빨간색 라인이 생김)
    이유는 main package 가 둘 이상 존재하기 때문입니다.

     
     
     
    더 나아가서 시스템적인 관점에서 말씀드리면,
    main function 은 컴파일러에 의해서 특별하게 인식된다고 말씀드렸습니다.
    왜냐하면 main function 은 프로그램의 entrypoint 이기 때문인데요.
    컴파일 과정을 끝마친 프로그램은 바이너리 파일로 변환됩니다. (사실 컴파일이라는 것이 binary file 을 만드는 과정입니다.)
    그리고 해당 binary 프로그램이 실행되어 프로세스가 될 때, 본격적인 기능이 수행됩니다.
    Spring 같은 서버 프로그램이라고 하면 http 포트를 리스닝하면서 여러가지 요청을 처리하는 기능이 동작할 것이고,
    Database 같은 프로그램의 경우에도 클라이언트의 query 요청을 받아 데이터를 처리합니다.
    그리고 내부적으로 disk IO 나 Replication 을 위하 다른 데이터베이스와의 네트워크 연결도 있겠죠.
     
    즉, 컴파일된 바이너리 파일은 작성된 로직에 따라 기능이 수행됩니다.
    그리고 이러한 모든 기능의 시작점이 main function 이고 main function 의 메모리 상의 위치가 프로그램의 entry point 입니다.
     
    CPU 는 실행된 프로세스의 entrypoint 에 해당하는 memory address 를 PC (Program Counter) 로 fetch 하여
    sequential 하게 모든 로직을 수행합니다.
     
     

    * packages

    main package 가 아닌 다른 패키지들은 directory 의 이름을 따라갑니다.
    그렇기 때문에 파일들의 성격에 따라 directory 의 이름을 짓는 것이 중요합니다.
    그리고 특정 directory 아래에 존재하는 모든 파일들은 같은 패키지에 속하게 됩니다.
     
    예를 들어보겠습니다.
    utility 디렉토리를 만들어, filesystem 과 http 네트워크 통신을 위한 패키지를 생성합니다.
     
    <file directory>

    /project
    	/files
    		/test.txt
    	/utility
    		/file.go
    		/http.go
    	/main.go
    	/go.mod

     

    <text.txt>

    this is test.txt.

     

    <file.go>
    ReadFile 함수는 인자로 전달받은 fileName 파일을 읽어들여
    File 의 내용을 print 하는 함수입니다.
     

    package utility
    
    import (
    	"os"
    )
    
    func ReadFile(fileName string) {
    	file, _ := os.Open(fileName)
    	buffer := make([]byte, 100)
    	file.Read(buffer)
    	print(string(buffer))
    
    }

     

    <http.go>
    Get 함수는 인자로 전달받은 Url 을 http get 요청을 시도하고 응답을 print 하는함수입니다.
     

    package utility
    
    import (
    	"fmt"
    	"io/ioutil"
    	"net/http"
    )
    
    func Get(url string) {
    	response, _ := http.Get(url)
    	defer response.Body.Close()
    
    	// 결과 출력
    	content, _ := ioutil.ReadAll(response.Body)
    	fmt.Print(string(content))
    }

     
    <main.go>
     

    package main
    
    import "project/utility"
    
    func main() {
    	filePath := "./files/test.txt"
    	utility.ReadFile(filePath)
    
    	url := "https://naver.com"
    	utility.Get(url)
    }

     

    utility 디렉토리를 생성하였습니다.
    utility 디렉토리은 곧 utility 패키지가 됩니다.
    그리고 utility 디렉토리 내부에는 http.go 파일과 file.go 파일이 있습니다.
    이는 곧 utility 패키지 내부에 http 와 file 이라는 모듈이 생성된 것으로 볼 수 있습니다.
    이로써 현 프로젝트에서 file system 과 http network 관련 utility 기능들을 사용할 수 있게 되었습니다.
     
    main.go 에서 utility 를 import 하여 해당 기능을 사용합니다.
     
    <결과>
     

    // test.txt content
    this is test.txt. 
    
    
    // http Get content
     <!doctype html> <html lang="ko" class="fzoom"> <head> <meta charset="utf-8"> <meta name="Referrer" content="origin">

     

    파일 구조적인 관점에서 보았을 때,
    project/utilitiy/http.go
    project/utilitiy/file.go
     
    utility 디렉토리 하위의 http.go 와 file.go 는 utility 패키지에 속하게 되며,
    go 에서 파일 구조와 패키지은 서로 깊이 관여하게 됩니다.
    그래서 디렉토리명과 패키지의 관계를 이해하며 프로젝트의 struct 를 고려해야합니다.
     
     

    반응형

    'Language > Golang' 카테고리의 다른 글

    golang struct 이해하기  (0) 2023.09.18
    golang cobra  (0) 2023.01.27
    Go-modules  (0) 2022.04.15
    [Sarama] Sarama 로 Kafka Producer 만들어보기 ( Golang )  (0) 2021.12.04
Designed by Tistory.