---
id: c90263519492728e7cc2d0ce840057b6
author: Yunjin Lee
title: Panggilan Sistem Linux Langsung dalam Go Murni dengan syscall.Syscall dan unsafe.Pointer
description: Pemanggilan system call kernel Linux seperti SYS_SYSINFO secara langsung dari Go murni menggunakan struct yang selaras dengan ABI, unsafe.Pointer, dan paket syscall standar tanpa cgo.
language: id
date: 2025-10-26T12:31:21.655228078Z
path: /blog/posts/go-syscall-is-a-brilliant-replacement-of-low-level-i-o-za50951e1
category: lowlevel
---

## Ringkasan

Kita akan mempelajari system call langsung di Go.
Karena Go menawarkan pesan kesalahan compiler yang ketat dan GC yang kaku, lebih baik mengganti panggilan tingkat rendah dengan Pure Go.
Untungnya, sebagian besar pemanggilan fungsi C telah diimplementasikan ulang sepenuhnya di Go, dengan cara yang baik dan modern.
Mari kita lihat contohnya.

## System Call

System call adalah permintaan langsung ke sistem operasi.
Karena sistem biasanya ditulis dengan gaya yang kaku dan kuno karena berjalan langsung di atas perangkat keras, kita perlu mempertimbangkan bahwa pemanggilannya harus menyampaikan bentuk permintaan yang ketat dan benar.
Oleh karena itu, meskipun kita tidak memerlukan beberapa variabel, kita tetap harus mengisi ukurannya terlepas dari penggunaannya.
Mari kita periksa dengan contoh yang berfungsi penuh.

## Contoh Lengkap

```go
package main
import (
	"fmt"
	"syscall"
	"unsafe"
)

type sysinfo_t struct {
	Uptime    int64
	Loads     [3]uint64
	Totalram  uint64
	Freeram   uint64
	Sharedram uint64
	Bufferram uint64
	Totalswap uint64
	Freeswap  uint64
	Procs     uint16
	Pad       uint16
	_         [4]byte
	Totalhigh uint64
	Freehigh  uint64
	MemUnit   uint32
	_         [4]byte
}

func main() {
	var info sysinfo_t
	_, _, errno := syscall.Syscall(syscall.SYS_SYSINFO, uintptr(unsafe.Pointer(&info)), 0, 0)
	if errno != 0 {
		fmt.Println("sysinfo syscall failed:", errno)
		return
	}

	scale := float64(1 << 16)
	fmt.Printf("Uptime: %d seconds\n", info.Uptime)
	fmt.Printf("Load Average: %.2f %.2f %.2f\n",
		float64(info.Loads[0])/scale,
		float64(info.Loads[1])/scale,
		float64(info.Loads[2])/scale)
	fmt.Printf("Memory: total=%d MB free=%d MB buffer=%d MB\n",
		info.Totalram*uint64(info.MemUnit)/1024/1024,
		info.Freeram*uint64(info.MemUnit)/1024/1024,
		info.Bufferram*uint64(info.MemUnit)/1024/1024)
	fmt.Printf("Swap: total=%d MB free=%d MB\n",
		info.Totalswap*uint64(info.MemUnit)/1024/1024,
		info.Freeswap*uint64(info.MemUnit)/1024/1024)
	fmt.Printf("Processes: %d\n", info.Procs)
}
```

Contoh ini menyertakan semua variabel, dan mencetak informasi sistem terkini secara lengkap.
Kita dapat membandingkan kode ini dengan gembok dan kunci.
`syscall.SYS_SYSINFO` adalah kunci yang membuka gembok yang berada di dalam kernel.
Oleh karena itu, menggunakan kunci yang tepat untuk gembok itu penting.
Apa yang akan terjadi jika kita menggunakan `syscall.SYS_GETPID` untuk pemanggilan ini?
Ini adalah kunci untuk gembok yang berisi Process ID.
Ini akan mencoba mengambil PID dari ruang informasi sistem.
Akibatnya, tidak ada informasi yang dapat dibaca dengan benar; pemanggilan tersebut harus dikembalikan dalam keadaan gagal.

Sekarang, kita perlu mengetahui item apa saja yang terdapat di dalamnya, dan bagaimana item-item tersebut diurutkan.
Pada slot pertama gembok, terdapat Uptime, dengan ukuran 2^64.
Jika kita mencoba membacanya dengan 2^32, urutan bit tidak terbaca secara utuh.
Kita tidak dapat menggunakan potongan biner parsial seperti ini kecuali kita akan menulis trik tingkat rendah.

Setelah membaca 64 bit data biner, barulah kita sampai pada slot kedua.
Slot ini hanya dapat dibaca dengan akurat ketika kita sudah membaca bilangan bulat 64-bit sebelumnya.

Dengan mengulangi alur yang ketat dan logis ini untuk memperoleh informasi yang tepat dari sistem, kita dapat menangani data yang dibaca dengan benar.

## Cara Melewati 'Nama Variabel'

Meskipun kita tidak dapat 'melewati' variabel itu sendiri, penting untuk membedakan antara variabel yang digunakan dan yang dibuang.
Jika penggunaan program sudah cukup jelas, lebih baik menggunakan variabel tanpa nama sebagai penampung daripada memberi label pada setiap nilai, meskipun nilai tersebut tidak akan digunakan selamanya.
Mari kita periksa hal ini dengan sebuah contoh, "Free Memory Checker"

## Contoh - Free Memory Checker

Saat memeriksa Free Memory/Swap, kita tidak memerlukan informasi lain yang menunjukkan sumber daya berbeda.
Untuk mencapai visibilitas yang lebih baik, Anda dapat membuat variabel anonim untuk menampung ruang tertentu.

```go
package main

import (
	"fmt"
	"syscall"
	"unsafe"
)

type sysinfo_t struct {
	_          int64
	_         [3]uint64
	Totalram  uint64
	Freeram   uint64
	Sharedram uint64
	Bufferram uint64
	Totalswap uint64
	Freeswap  uint64
	_         uint16  // anonim, dan yang tidak digunakan ditandai sebagai _
	_         uint16
	_         [4]byte
	_         uint64
	_         uint64
	MemUnit   uint32
	_         [4]byte
}

func main() {
	var info sysinfo_t
	_, _, errno := syscall.Syscall(syscall.SYS_SYSINFO, uintptr(unsafe.Pointer(&info)), 0, 0)
	if errno != 0 {
		fmt.Println("sysinfo syscall failed:", errno)
		return
	}

	fmt.Printf("Memory: total=%d MB free=%d MB buffer=%d MB\n",
		info.Totalram*uint64(info.MemUnit)/1024/1024,
		info.Freeram*uint64(info.MemUnit)/1024/1024,
		info.Bufferram*uint64(info.MemUnit)/1024/1024)
	fmt.Printf("Swap: total=%d MB free=%d MB\n",
		info.Totalswap*uint64(info.MemUnit)/1024/1024,
		info.Freeswap*uint64(info.MemUnit)/1024/1024)
}
```

Akibatnya, variabel dibaca tanpa label.
Meskipun nilai anonim sebenarnya disimpan ke dalam sebuah struktur, tidak ada label atau tanda yang dapat dibaca pada kode.

## Kesimpulan

- Menggunakan `syscall` dan `unsafe` di Go tetap lebih aman daripada C/CGo
- Jika Anda menulis proyek besar yang dapat diperluas dengan mudah:
  - Jangan membuat variabel anonim; berikan nama untuk setiap anggota.
- Jika Anda menulis proyek dengan penggunaan terbatas:
  - Anda dapat menggunakan variabel anonim untuk menampung ruang yang memang tidak digunakan.
- `syscall` di Go powerful dan modern untuk menangani panggilan tingkat rendah

## Bacaan Lanjutan

[syscall](https://pkg.go.dev/syscall)
[unsafe](https://pkg.go.dev/unsafe)
[x/sys/unix](https://pkg.go.dev/golang.org/x/sys/unix)
