golang

Golang Syscall Examples

Go’s syscall package offers a low-level interface to interact with the core operating system. It allows us to access the system calls and perform the system-level operations that are not readily available in higher-level packages. In this article, we will explore the several examples of using the syscall package which includes executing the processes, file the I/O operations, accessing the environment variables, and changing, creating, and removing the working directory.

Example 1: Using the Golang Syscall Package to Exec the Process

The syscall package, along with the os/exec package, allows us to spawn new processes, set up the input/output streams, and handle the execution of commands.

package main
import (
    "os"
    "os/exec"
    "syscall"
)
func main() {
    binary, CheckErr := exec.LookPath("ls")
    if CheckErr != nil {
        panic(CheckErr)
    }

    args := []string{"ls", "-a",  "-l" ,"-h"}

    envir := os.Environ()

    RunErr := syscall.Exec(binary, args, envir)
    if RunErr != nil {
        panic(RunErr)
    }
}

In this example, we add the os, os/exec, and syscall packages which provide functionalities that are related to executing external commands and interacting with the operating system. After that, we deploy the main() function where we use the exec.LookPath() function to search for the binary executable file of the “ls” command in the system’s PATH.

Next, we create an array of “args” strings which holds the command and its arguments. In this case, the “ls” command is being invoked with the “-a” which displays all files including the hidden ones, the “-l” which is responsible for long format which displays a detailed information about the file, and the “-h” print file sizes in human-readable format flags. These arguments modify the behavior of the “ls” command when it is executed.

After that, a slice of strings that represents the existing environment variables can be obtained using the osEnviron() function. This slice is assigned to the “envir” variable. The environment variables can be used by executing the commands and passing them through the os.Environ() function to ensure that the child thread has a comparable environment as the parent thread. Finally, it executes the command using syscall.Exec(), passing the binary path, argument list, and environment variables.

Thus, the output displays all files including the hidden ones in a long format with human-readable file sizes:

Example 2: Using the Golang Syscall Package to Read the File Data

To read file data using the syscall package in Go, we can utilize the syscall.Open() and syscall.Read() functions.

package main
import (
"fmt"
"syscall"
)

func main() {
var MyFile = make([]byte, 64)
FileData, ex := syscall.Open("NewFile.txt", syscall.O_RDONLY, 0777)
if ex != nil {
fmt.Println("Exception:", ex)
}
for {

len, _ := syscall.Read(FileData, filedata)
if len <= 0 {
break
}
fmt.Println("File content: ")
fmt.Print(string(filedata[:len]))
}
}

In this example, we create the “MyFile” variable which is a byte slice of size 64 in the main() method. After that, we deploy the syscall.Open() function to open the “NewFile.txt” file in read-only mode as the syscall.O_RDONLY with the file permissions that are set to 0777 is passed as an argument.

Next, we create the “for” loop that utilizes the syscall.Read() function to obtain the data from the “FileData” file descriptor into the “MyFile” byte slice. The “len” variable stores the number of bytes read, and an underscore (_) is used to ignore the error that is returned by the syscall.Read() method. If the “len” variable is less than or equal to 0, it means that the end of the file is reached, and the loop is terminated using the break statement.

The output here opens the “NewFile.txt” file using the system calls and read the contents in chunks of 64 bytes:

Example 3: Using the Golang Syscall Package to Get the System Environment Variables

Additionally, we can use the syscall package Getenv() function to get the system environment variables.

package main

import (
"fmt"
"syscall"
)

func main() {

environmentVar := syscall.Environ()

fmt.Println("System Environment variables:")
for i := range environmentVar {
fmt.Println(environmentVar[i])
}
}

In this example, we begin within the main() function where the “environmentVar” variable is declared which is a slice of strings. The environment variables are retrieved as a slice of strings using the syscall.Environ() function. The retrieved slice is assigned to the “environmentVar” variable. Next, we call the loop that executes over the “environmentVar” slice using the “range” loop operation. The loop continues through each slice element and the index is discarded using the identifier for a blank string (_).

Hence, we get the output which shows the environment variables that are available in the system’s execution:

Example 4: Using the Golang Syscall Package to Change the Existing Directory

Next is to change the current working directory which is achieved using the syscall Chdir() function.

package main
import "fmt"
import "os"
func main() {
  PresentDir, Code_err := os.Getwd()
  if Code_err != nil {
    fmt.Println(Code_err)
    return

  }

  fmt.Println(PresentDir)
  Code_err = os.Chdir("\Users\Hp\MyApp\go\bin")
  PresentDir, Code_err = os.Getwd()
  if Code_err != nil {
    fmt.Println(Code_err)
    return
  }
  fmt.Println(PresentDir)

In this example, we call the os.Getwd() to get the current working directory and assign it to the “PresentDir” variable. It also captures the potential error in the Code_err variable. Then, we deploy the os.Chdir() method to change the current working directory to “/Users/Hp/MyApp/go/bin”. We fetch the current working directory again using os.Getwd() and assign it to the “PresentDir” variable. Additionally, the Code_err field is used to catch any potential errors. With this, we check if there is an error while retrieving the current working directory.

There, we can see the changed directory in the output that is specified previously:

Example 5: Using the Golang Syscall Package to Create the Directory

Now, to create the directory in Golang, we use the following syscall.Mkdir() function:

package main

import (
"fmt"
"syscall"
)

func main() {

e1 := syscall.Mkdir("/test/MyDir", 0754)

if e1 == nil {
fmt.Println("Created")
}
}

In this example, we use the syscall.Mkdir() function to create a new directory named “/test/MyDir” with the permission mode that is set to 0754. The function call returns an error that is assigned to the “e1” variable. After that, we examine if the “e1” error is nil which indicates that the directory is successfully created.

The output displays the “Created “ message which indicates that the specified directory is created:

Example 6: Using the Golang Syscall Package to Remove the Directory

However, to remove a directory using the syscall package in Go, we can use the syscall.Rmdir() function.

package main
import (
   "fmt"
   "syscall"
)

func main() {
   dirIs := "MyDir"
   errIs := syscall.Rmdir(dirIs)
   if errIs != nil {
      fmt.Println(errIs)
   } else {
      fmt.Println("Directory", dirIs, "removed")
   }
}

In this example, we have the “MyDir” directory which is assigned to the “dirIs” variable. The “Rmdir” function is then called with the directory name as its argument, attempting to remove the specified directory. Then, we define the “errIs” variable which holds the error details while removing the given directory. Next, if the removal process is successful and no error occurs, we display a message stating that the directory has been removed.

Hence, the directory is removed as displayed in the output. Note that the directory should be empty because the Rmdir() function does not delete the non-empty directories:

Conclusion

The syscall package is useful in situations that require more control and platform-specific functionality. We utilize the different operations of the Go syscall package very efficiently. These examples provide a starting point to utilize the syscall package in the Go programs.

About the author

Kalsoom Bibi

Hello, I am a freelance writer and usually write for Linux and other technology related content