os.Chmod(path, 0o755) sets a file’s mode to rwxr-xr-x, the same as chmod 755 in a shell. 0o755 is an octal literal, the form Go has accepted since 1.13; older code writes 0755, which Go still reads as octal.
if err := os.Chmod("deploy.sh", 0o755); err != nil {
log.Fatal(err)
}
info, _ := os.Stat("deploy.sh")
fmt.Println(info.Mode()) // -rwxr-xr-x
fmt.Printf("%o\n", info.Mode().Perm()) // 755
The tool below reads 755 the same way: owner rwx, group and others r-x.
Decimal 755
os.Chmod("deploy.sh", 755) compiles, because 755 is a valid FileMode, and leaves the file at --wxrw--wx. Decimal 755 is octal 1363; C, Python and Node would set all four digits, sticky bit included, but Go keeps only the low nine bits, 363. Type 363 into the tool to see -wxrw--wx: the owner can’t read the file and the group can’t run it.
Setuid, setgid and sticky aren’t octal digits in Go
A FileMode uses Go’s own bit layout, the same on every system. The nine permission bits sit where Unix puts them, but the special bits are flags at the top of the uint32, so the leading 4 of 0o4755 means nothing to os.Chmod:
os.Chmod("server", 0o4755) // ls -l: -rwxr-xr-x, setuid silently dropped
os.Chmod("server", 0o755|os.ModeSetuid) // ls -l: -rwsr-xr-x
Use os.ModeSetuid, os.ModeSetgid and os.ModeSticky; os.Chmod’s docs say those three and the permission bits are what it uses on Unix. Go also prints them its own way: info.Mode() for that file is urwxr-xr-x, where ls shows -rwsr-xr-x and the tool shows 4755.
Printing an fs.FileMode
os.FileMode is the same type as fs.FileMode, and its String method gives the ls-style form:
fmt.Println(fs.FileMode(0o755), fs.FileMode(0o755)|fs.ModeDir) // -rwxr-xr-x drwxr-xr-x
fmt.Printf("%o %#o\n", fs.FileMode(0o755), fs.FileMode(0o755)) // 755 0755
To add one bit, as chmod u+x does, start from the current mode: os.Chmod(p, info.Mode()|0o100) turns 644 into 744.
os.WriteFile and the umask
os.WriteFile("a.txt", data, 0o666) // -rw-r--r-- under umask 022
os.WriteFile("a.txt", data, 0o600) // still -rw-r--r--
os.MkdirAll("d/e", 0o777) // drwxr-xr-x
The mode applies only when the file is created, minus the umask, and an existing file keeps its mode. For a file that must be private, call os.Chmod after writing, or syscall.Umask(0o077) first on Unix, which gave -rw-------; the umask is process-wide, so set it back.
Windows
Per the os.Chmod docs, Windows uses only the 0o200 bit, which sets or clears the read-only attribute. Use 0o400 for read-only and 0o600 for writable.