Go 常用包: 系統基本操作包 - OS

1. 介紹

os包中提供了操作系統函數的接口,是一個比較重要的包。它的作用主要是在服務器上進行系統的基本操作,如文件操作、目錄操作、執行命令、信號與中斷、進程、系統狀態等等。下面分模塊歸納一些常用函數。

2. 系統信息

2.1 函數列表

14hgXB

2.2 代碼示例

a. 示例一

// 系統相關
func TestSystemInfo(t *testing.T) {
 hostname, _ := os.Hostname()
 // 主機名: huideMacBook-Pro.local
 fmt.Printf("主機名:%v \n", hostname)
 // 調用者所在進程的進程ID: 42862
 fmt.Printf("調用者所在進程的進程ID: %v \n", os.Getpid())
 // 調用者所在進程的進程的父進程ID: 42861 
 fmt.Printf("調用者所在進程的進程的父進程ID: %v \n", os.Getppid())
}

b. 示例二

func TestExit(t *testing.T) {
 fmt.Println("調用前打印...")
 // 調用退出程序:code範圍應在 0 <= x <= 125
 os.Exit(0)
 // 後面代碼不會執行
 fmt.Println("調用後,這裏不會輸出")
}
/** 輸出
=== RUN   TestExit
調用前打印...

Process finished with exit code 0
*/

3. 環境變量

3.1 函數列表

zfs89C

3.2 代碼示例

// 環境變量相關
func TestEnv(t *testing.T) {
 // 所有環境變量
 fmt.Printf("所有環境變量:%+v \n", os.Environ())
 // 設置環境變量
 _ = os.Setenv("my-name", "張三")
 // 獲取環境變量
 fmt.Printf("獲取環境變量: %v \n", os.Getenv("my-name"))
 // 清空所有環境變量
 os.Clearenv()
 fmt.Printf("清空環境變量後:%+v \n", os.Environ())
}

輸出:

=== RUN   TestEnv
所有環境變量:[PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin __CFBundleIdentifier=com.jetbrains.goland SHELL=/bin/zsh SECURITYSESSIONID=186a6 GOPATH=/Users/hui/go TERM=xterm-256color USER=hui GOROOT=/usr/local/go TMPDIR=/var/folders/8f/vnx2y1h57nzbd2p4vtcl6hv80000gn/T/ LaunchInstanceID=D9F74359-45B7-45F3-B74C-67CEA4DB8D9D COMMAND_MODE=unix2003 GO111MODULE=on SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.5K5WgUh7Hh/Listeners GOPROXY=https://goproxy.cn,direct XPC_FLAGS=0x0 __CF_USER_TEXT_ENCODING=0x1F5:0x19:0x34 LOGNAME=hui XPC_SERVICE_NAME=application.com.jetbrains.goland.15834002.15834933 PWD=/Users/hui/Project/Go/gin-learn/test HOME=/Users/hui GOARCH=amd64 GOBIN=/Users/hui/Project/Go/gopath/bin GOCACHE=/Users/hui/Library/Caches/go-build GOENV=/Users/hui/Library/Application Support/go/env GOHOSTARCH=amd64 GOHOSTOS=darwin GOMODCACHE=/Users/hui/go/pkg/mod GOOS=darwin GOSUMDB=sum.golang.org GOTOOLDIR=/usr/local/go/pkg/tool/darwin_amd64 GCCGO=gccgo AR=ar CC=clang CXX=clang++ CGO_ENABLED=1] 
獲取環境變量: 張三 
清空環境變量後:[] 
--- PASS: TestEnv (0.00s)
PASS

4. 文件相關

關於文件相關的函數,參見之前的文章 Go 學習 (二十四): 文件操作

5. 進程相關

5.1 方法列表

P45cqU

上表中 p 代表: *os.Process,  ps 代表: *os.ProcessState

5.2 代碼示例

func TestCreateProcess(t *testing.T) {
 // 創建一個新進程執行;ls /
 args := []string{"/"}
 process, err := os.StartProcess("/bin/ls", args, &os.ProcAttr{})
 if err != nil {
  t.Error("創建新進程失敗: " + err.Error())
  return
 }
 fmt.Printf("當前新線程信息: %+v \n", process)

 // 2秒後向進程發送信號
 time.AfterFunc(2 * time.Second, func() {
  fmt.Println("發送進程退出信號...")
  _ = process.Signal(os.Kill)
 })
 // 手動阻塞看是否執行:發送信號
 time.Sleep(3 * time.Second)

 // 等待進程退出,返回ProcessState類型
 processState, _ := process.Wait()
 // 返回一個已退出進程的id
 fmt.Printf("當前進程Id: %v \n", processState.Pid())
 // 報告進程是否已退出
 fmt.Printf("進程是否已退出: %v \n", processState.Exited())
 // 報告進程是否成功退出,如在Unix裏以狀態碼0退出。
 fmt.Printf("進程是否成功退出: %v \n", processState.Success())
 // 返回已退出進程及其子進程耗費的系統CPU時間。
 fmt.Printf("進程及子進程耗費系統CPU時間: %v \n", processState.SystemTime())
 // 返回已退出進程及其子進程耗費的用戶CPU時間。
 fmt.Printf("進程及子進程耗費用戶CPU時間: %v \n", processState.UserTime())
 fmt.Printf("進程狀態: %s \n",processState.String())
}

輸出:

=== RUN   TestCreateProcess
當前新線程信息: &{Pid:46859 handle:0 isdone:0 sigMu:{w:{state:0 sema:0} writerSem:0 readerSem:0 readerCount:0 readerWait:0}} 
當前進程Id: 46859 
進程是否已退出: true 
進程是否成功退出: true 
進程及子進程耗費系統CPU時間: 1.563ms 
進程及子進程耗費用戶CPU時間: 503µs 
發送進程退出信號...
進程狀態: exit status 0 
--- PASS: TestCreateProcess (3.00s)
PASS

6. 執行命令

os/exec包執行外部命令。它包裝了os.StartProcess函數以便更容易的修正輸入和輸出,使用管道連接I/O,以及其它的一些優化。

6.1 方法列表

ZCRmYD

6.2 使用示例

1. LookPath
// 在環境變量PATH中搜索可執行文件
func TestLookPath(t *testing.T) {
 path, err := exec.LookPath("go")
 if err != nil {
  t.Error(err)
 }
 fmt.Println(path)
}
/** 輸出
=== RUN   TestLookPath
/usr/local/go/bin/go
--- PASS: TestLookPath (0.00s)
PASS
*/
2.Run
// 使用Run()執行命令
func TestRun(t *testing.T) {
 // 執行: go version
 cmd := exec.Command("sleep", "3s")
 // 具體執行
 err := cmd.Run()
 if err != nil {
  t.Errorf("執行失敗:%v\n",err)
 }
 fmt.Printf("cmd.Path: %v \n",cmd.Path)
 fmt.Printf("cmd.Args: %v \n",cmd.Args)
}
/** 輸出
=== RUN   TestRun
cmd.Path: /bin/sleep 
cmd.Args: [sleep 3s] 
--- PASS: TestRun (3.01s)
PASS
*/
3. Start
// 使用Start執行命令
func TestStart(t *testing.T) {
 // 執行: go version
 cmd := exec.Command("sleep", "3s")
 // Start開始執行c包含的命令,但並不會等待該命令完成即返回
 err := cmd.Start()
 if err != nil {
  t.Errorf("執行失敗:%v\n",err)
 }
 //Wait會阻塞直到該命令執行完成
 err = cmd.Wait()
 fmt.Printf("執行完成: %v \n",err)
 fmt.Printf("cmd.Path: %v \n",cmd.Path)
 fmt.Printf("cmd.Args: %v \n",cmd.Args)
}

/** 輸出
=== RUN   TestStart
執行完成: <nil> 
cmd.Path: /bin/sleep 
cmd.Args: [sleep 3s] 
--- PASS: TestStart (3.00s)
PASS
*/
4.Output
// 執行命令並獲取輸出結果
func TestOutput(t *testing.T) {
 // 執行: go version
 output, _ := exec.Command("go", "version").Output()
 fmt.Printf("結果: %s \n",output)
 // 執行: du -sh .
 output2, _ := exec.Command("du", "-sh",".").Output()
 fmt.Printf("結果: %s \n",output2)
}

/** 輸出
=== RUN   TestOutput
結果: go version go1.15.5 darwin/amd64
 
結果:  36K .
 
--- PASS: TestOutput (0.02s)
PASS
*/
5.CombinedOutput
// 執行命令並返回標準輸出和錯誤輸出合併的切片
func TestCombinedOutput(t *testing.T) {
 // 執行: go version-1 故意寫錯
 output, _ := exec.Command("go", "version-1").CombinedOutput()
 fmt.Printf("結果: %s \n",output)
}

/** 輸出
=== RUN   TestCombinedOutput
結果: go version-1: unknown command
Run 'go help' for usage.
 
--- PASS: TestCombinedOutput (0.01s)
PASS
*/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/KjfIrBJxYgCKLOHhJmzkNA