// executable
if stat, err := os.Stat(filename); err != nil {
panic(err)
}
if stat.Mode().Perm() & 0111 == 0000 {
fmt.Printf("%s not executable\n", filename)
}
Last active
August 12, 2023 14:16
-
-
Save chaosmatrix/bc4a3d423273becbda3657102a12c5cd to your computer and use it in GitHub Desktop.
golang tips
strconv
// "000123" -> 123
// "123" -> 123
strconv.Atoi
mode operations
Basic
Golang: x % y
is negative or positive base on x > 0
or x < 0
, x % y != (x % y + y) % y
Python: x % y
is always positive not matter x > 0
or x < 0
, x % y = (x %y + y) % y
(x % y + y) % y = (x % y) + (y % y)
to handle case x < 0, make sure result alwasy >= 0
OR
if x % mod < 0 {
x = x % mod + mod
}
x * y % m = (( x % m) * (y % m)) % m = (x % m) * y % m
Example
Golang:
fmt.Printf("%d %% %d = %d\n", 6, 8, 6%8)
fmt.Printf("%d %% %d = %d\n", -6, 8, -6%8)
fmt.Printf("(%d %% %d + %d) %% %d = %d\n", -6, 8, 8, 8, (-6%8+8)%8)
fmt.Printf("(%d %% %d + %d) %% %d = %d\n", 6, 8, 8, 8, (6%8+8)%8)
Output:
6 % 8 = 6
-6 % 8 = -6
(-6 % 8 + 8) % 8 = 2
(6 % 8 + 8) % 8 = 6
Python:
>>> 6 % 8
6
>>> -6 % 8
2
>>> (-6 % 8 + 8) % 8
2
>>> (6 % 8 + 8) % 8
6
>>>
unsafe
get pointer address
*(*uint64)(unsafe.Pointer(&v))
net.Dialer
net.Dialer will resolve domain to get addresses, both ipv4 and ipv6.
abstruct:
- in dual stack, first try IPv6, then fallback into IPv4 in
net.Dialer.FallbackDelay
- not dual stack, try all addresses in sequence before timeout.
more details:
- code
net/dial.go
- rfc: https://www.rfc-editor.org/rfc/rfc6555.html
reduce binary package size
- go build -ldflags '-s -w'
~70%
- bad for debuging
- upx https://github.com/upx/upx/releases
~50%
defer
When:
- execute before function return
Rules:
- A deferred function’s arguments are evaluated when the defer statement is evaluated.
- defer f(v) // v is argument
- defer f1().f() // f1() is argument
- Deferred function calls are executed in Last In First Out order after the surrounding function returns.
- Deferred functions may read and assign to the returning function’s named return values.
pidfall
defer f1().f2().f3() // consider f1().f2() as argument for function f3()
equal with
v := f1().f2()
defer v.f3()
Golang Upgrade Version
go get
only check library's version, won't re-compile tools aftergo version
change
Example
s = "ab"
s[i] is uint8 type
for _, r := range s {
// r is rune type, is int32 type
}
int(s[0] - s[1]) => int(uint8(uint8(s[1]) - uint8(s[0])))
s[0] < s[1], so, s[0] - s[1] = -1, as uint8, will overflow as 255
int(s[0]) - int(s[1]) = -1
net.IP
Rules:
- Both IPv4 and IPv6 address store as IPv6 address
To16()
can convert IPv4 to IPv6 (because IPv4 store as IPv6 format)To4()
will check if the IP address is valid IPv4 or not (::ffff:808:808
is valid IPv4)String()
: all valid IPv4 address will be show as IPv4 format (::ffff:808:808
will be show as8.8.8.8
)- When you want to know a string is valid IP and distinguish between IPv4 and IPv6, it's good to use netip.ParseAddr() in net/netip
Example
input string | net.ParseIP() | String() | To4() |
---|---|---|---|
2607:f8b0:4006:81f::2004 | net.IP{0x26, 0x7, 0xf8, 0xb0, 0x40, 0x6, 0x8, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x4} | 2607:f8b0:4006:81f::2004 | nil |
8.8.8.8 | net.IP{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x8, 0x8, 0x8, 0x8} | 8.8.8.8 | |
::ffff:808:808 | net.IP{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x8, 0x8, 0x8, 0x8} | 8.8.8.8 |
Cookbooks:
Check an Input string is valid IPv4 address (dotted decimal notations)
ip := net.ParseIP(s)
if ip != nil && ip.To4() != nil && !strings.Contains(s, ":") {
return true
}
return false
Check an IP is valid IPv6 address
All IP addresses are IPv6 address, you can only check an IP address is valid IPv4 or not
ip := net.ParseIP(s)
if ip != nil && ip.To4() == nil {
return false
}
return ip != nil
net/netip
package main
import (
"fmt"
"net/netip"
)
func main() {
ts := []string {
"2001:db8::68",
"8.8.8.8",
"::ffff:808:808",
"0:0:0:0:0:ffff:0808:0808",
"0000:0000:0000:0000:0000:ffff:0808:0808",
}
for _, s := range ts {
addr, err := netip.ParseAddr(s)
if err == nil {
fmt.Printf("ip: %s, is_ipv4: %v, is_ipv4Toipv6: %v, is_ipv6: %v, string: %s\n", s, addr.Is4(), addr.Is4In6(), addr.Is6(), addr.String())
} else {
fmt.Printf("[+] invalid ip %s\n", s)
}
}
}
Output:
ip: 2001:db8::68, is_ipv4: false, is_ipv4Toipv6: false, is_ipv6: true, string: 2001:db8::68
ip: 8.8.8.8, is_ipv4: true, is_ipv4Toipv6: false, is_ipv6: false, string: 8.8.8.8
ip: ::ffff:808:808, is_ipv4: false, is_ipv4Toipv6: true, is_ipv6: true, string: ::ffff:8.8.8.8
ip: 0:0:0:0:0:ffff:0808:0808, is_ipv4: false, is_ipv4Toipv6: true, is_ipv6: true, string: ::ffff:8.8.8.8
ip: 0000:0000:0000:0000:0000:ffff:0808:0808, is_ipv4: false, is_ipv4Toipv6: true, is_ipv6: true, string: ::ffff:8.8.8.8
time.Timer vs time.Ticker
Diff:
- Timer need to Reset every time when it fired
- Ticker auto reset every time when it fired
Warning:
- when the job wast more than ticker duration, there might has more than one job executed or lose some ticker
The difference of them show as code
// timer
for {
time.Sleep(d)
do_some_thing
// timer reset
}
// ticker
for {
time.Sleep(d)
go func() {
do_some_thing
}()
// wait next ticker
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
sync
Once
func (o *Once) Do(f func())
useatomic
make concurrency caller return immediately, useMutex
protect callingf
golang source code:
src/sync/once.go