1. OS 라이브러리 기초
Golang의 os
패키지는 운영 체제 기능에 대한 플랫폼 독립적인 인터페이스를 제공합니다. 다음으로는 os
패키지를 사용하여 파일 열기, 닫기, 읽기, 쓰기, 파일 속성 획득 및 설정하는 방법에 대해 알아보겠습니다.
1.1 파일 열기와 닫기
Go 언어에서는 os.Open
함수를 사용하여 파일을 열 수 있으며, 이는 *os.File
객체와 오류를 반환합니다. 파일을 열면 읽기, 쓰기 및 기타 작업을 수행할 수 있습니다. 작업을 마치면 file.Close
를 호출하여 파일을 닫고 해당 리소스를 해제해야 합니다.
다음은 파일을 열기 위한 예시입니다:
package main
import (
"fmt"
"os"
)
func main() {
// 현재 디렉토리에 있는 test.txt 파일 열기
file, err := os.Open("test.txt")
if err != nil {
// 파일 열기 오류 처리
fmt.Println("파일 열기 오류:", err)
return
}
// 파일이 최종적으로 닫히도록 defer 문 사용
defer file.Close()
// 파일 처리 작업...
fmt.Println("파일이 성공적으로 열렸습니다")
}
위 코드에서는 defer
문을 사용하여 file.Close
가 반드시 실행되도록 보장합니다. 이는 Go 언어에서 리소스 정리를 위한 일반적인 관행입니다.
1.2 파일 읽기 및 쓰기 작업
os.File
타입에는 파일 읽기 및 쓰기 작업에 사용할 수 있는 Read
및 Write
메서드가 있습니다. Read
메서드는 파일에서 데이터를 바이트 슬라이스로 읽고, Write
메서드는 바이트 슬라이스에서 파일로 데이터를 쓸 수 있습니다.
다음 예제는 파일에서 읽고 쓰는 방법을 보여줍니다:
package main
import (
"fmt"
"os"
)
func main() {
// 파일 열기
file, err := os.OpenFile("test.txt", os.O_RDWR, 0644)
if err != nil {
fmt.Println("파일 열기 오류:", err)
return
}
defer file.Close()
// 파일 내용 쓰기
message := []byte("안녕, 고퍼들!")
_, writeErr := file.Write(message)
if writeErr != nil {
fmt.Println("파일 쓰기 오류:", writeErr)
return
}
// 파일 처음으로 이동하여 읽기
file.Seek(0, 0)
buffer := make([]byte, len(message))
_, readErr := file.Read(buffer)
if readErr != nil {
fmt.Println("파일 읽기 오류:", readErr)
return
}
fmt.Println("파일 내용:", string(buffer))
}
이 예제에서는 os.Open
대신 os.OpenFile
을 사용합니다. os.OpenFile
함수를 사용하면 파일을 열 때 사용할 모드와 권한을 지정할 수 있습니다. 위 예제에서는 os.O_RDWR
플래그를 사용하여 파일을 읽기-쓰기 모드로 열도록 합니다.
1.3 파일 속성과 권한
os
패키지의 함수를 사용하여 파일 상태 정보에 액세스하고 수정할 수 있습니다. os.Stat
또는 os.Lstat
을 사용하여 파일 크기, 권한, 수정 시간 등 파일에 대한 정보를 제공하는 os.FileInfo
인터페이스를 얻을 수 있습니다.
파일 상태를 얻는 방법 예시는 다음과 같습니다:
package main
import (
"fmt"
"os"
)
func main() {
fileInfo, err := os.Stat("test.txt")
if err != nil {
fmt.Println("파일 정보 가져오기 오류:", err)
return
}
// 파일 크기 출력
fmt.Printf("파일 크기: %d 바이트\n", fileInfo.Size())
// 파일 권한 출력
fmt.Printf("파일 권한: %s\n", fileInfo.Mode())
}
파일 이름을 변경하거나 파일의 권한을 수정해야 하는 경우, os.Rename
을 사용하여 파일의 이름을 변경하거나 os.Chmod
를 사용하여 파일 권한을 변경할 수 있습니다.
package main
import (
"fmt"
"os"
)
func main() {
// 파일 권한을 읽기 전용으로 변경
err := os.Chmod("test.txt", 0444)
if err != nil {
fmt.Println("파일 권한 변경 오류:", err)
return
}
// 파일 이름 변경
renameErr := os.Rename("test.txt", "renamed.txt")
if renameErr != nil {
fmt.Println("파일 이름 변경 오류:", renameErr)
return
}
fmt.Println("파일 작업 성공적으로 완료")
}
여기서 test.txt
파일의 권한을 읽기 전용으로 변경하고, 그런 다음 파일의 이름을 renamed.txt
로 변경합니다. 파일 권한을 수정할 때는 잘못된 권한 설정이 파일에 액세스할 수 없게 만들 수 있으므로 주의해야 합니다.
2. IO 라이브러리의 기본 사용
Go 언어에서 io
라이브러리는 I/O 기본 인터페이스를 제공합니다. io
라이브러리의 설계는 간결함과 일관된 인터페이스의 원칙을 따르며 파일 읽기/쓰기, 네트워크 통신, 데이터 버퍼링 등과 같은 다양한 유형의 I/O 작업에 기본 지원을 제공합니다.
2.2 Reader 및 Writer 인터페이스 사용
io.Reader
와 io.Writer
는 객체의 읽기 및 쓰기 작업을 지정하는 두 가지 기본 인터페이스입니다. 파일, 네트워크 연결, 버퍼 등과 같이 다양한 유형으로 구현됩니다.
io.Reader
io.Reader
인터페이스에는 Read 메서드가 있습니다:
Read(p []byte) (n int, err error)
이 방법은 io.Reader
에서 p
로 최대 len(p)
바이트의 데이터를 읽습니다. 읽은 바이트 수 n
(0 <= n
<= len(p
))와 발생한 오류가 반환됩니다.
샘플 코드:
package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("안녕, 세상!")
buf := make([]byte, 4)
for {
n, err := r.Read(buf)
if err == io.EOF {
break
}
fmt.Printf("읽은 바이트: %d, 내용: %s\n", n, buf[:n])
}
}
이 예에서는 문자열에서 데이터를 읽기 위해 strings.NewReader
를 만들고 데이터를 4바이트씩 읽습니다.
io.Writer
io.Writer
인터페이스에는 Write 메서드가 있습니다:
Write(p []byte) (n int, err error)
이 방법은 p
에서 데이터를 기본 데이터 스트림으로 쓰고, 쓰인 바이트 수와 발생한 오류가 반환됩니다.
샘플 코드:
package main
import (
"fmt"
"os"
)
func main() {
data := []byte("안녕, 세상!\n")
n, err := os.Stdout.Write(data)
if err != nil {
panic(err)
}
fmt.Printf("쓴 바이트: %d\n", n)
}
이 예시에서는 간단한 문자열을 표준 출력인 os.Stdout
에 씁니다. 이것은 io.Writer
의 구현으로 작동합니다.
2.3 고급 읽기/쓰기 함수
io
패키지는 데이터 복사와 지정된 양의 데이터를 읽는 등 일반적인 작업을 간편하게 처리할 수 있는 몇 가지 고급 기능을 제공합니다.
복사 함수
io.Copy
는 중간 버퍼 없이 io.Reader
에서 바로 데이터를 io.Writer
로 복사하는 편리한 방법입니다.
샘플 코드:
package main
import (
"io"
"os"
"strings"
)
func main() {
r := strings.NewReader("간단한 복사 작업 예시")
_, err := io.Copy(os.Stdout, r)
if err != nil {
panic(err)
}
}
이 예시에서는 문자열을 직접 표준 출력으로 복사합니다.
ReadAtLeast 함수
io.ReadAtLeast
함수는 지정된 양의 데이터가 반환되기 전에 최소한 지정된 양의 데이터가 io.Reader
에서 읽히도록 하는 데 사용됩니다.
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
샘플 코드:
package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("Go 언어 중국어 웹사이트")
buf := make([]byte, 14)
n, err := io.ReadAtLeast(r, buf, 14)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s\n", buf[:n])
}
이 예시에서 io.ReadAtLeast
는 buf
로 최소 14바이트의 데이터를 읽으려고 시도합니다.
이러한 고급 읽기/쓰기 함수를 사용하면 I/O 관련 작업을 더 효율적으로 처리할 수 있으며, 더 복잡한 프로그램 로직을 구축하는데 견고한 기반을 제공합니다.