I have my script "file.go" Built with "go build file.go" now I have "file.exe"
In the code I have "steamid := xxxxxxxxxxxxxxxx" Is there anyway when executing file.exe in cmd like "file.exe -steamid=xxxxxxxxxxxxxxxx"
code:
package main
import (
"crypto/md5"
"fmt"
)
func main() {
steamid := xxxxxxxxxxxxxxxx
h := md5.New()
h.Write([]byte("BE"))
for i := 0; i < 8; i++ {
h.Write([]byte{byte(steamid & 0xFF)})
steamid >>= 8
}
fmt.Printf("Battleye GUID: %x", h.Sum(nil))
}
I've gotten as far as here with new replys;
package main
import (
"crypto/md5"
"fmt"
"bufio"
"os"
"flag"
)
var SteamID string
func init() {
flag.StringVar(&SteamID, "steamid", "XXXXXXXXXXXXXXXXX", "17 Numbers SteamID")
}
func main() {
steamid := &SteamID
h := md5.New()
h.Write([]byte("BE"))
for i := 0; i < 8; i++ {
h.Write([]byte{byte(steamid & 0xFF)})
steamid >>= 8
}
fmt.Printf("Battleye GUID: %x", h.Sum(nil))
fmt.Print("\nPress 'Enter' to continue...")
bufio.NewReader(os.Stdin).ReadBytes('\n')
}
Error:
C:\Go\bin>go build file.go
# command-line-arguments
.\file.go:24: invalid operation: steamid & 255 (mismatched types *string and int)
.\file.go:25: invalid operation: steamid >>= 8 (shift of type *string)
the flag package included in the standard library does just that.
what you need to add in your script:
var SteamID string
func init() {
flag.StringVar(&SteamID, "steamid", "<insert default value>", "<insert help text>")
}
(in case you need to get it as an integer, use Int64Var instead)
then in your main function add:
flag.Parse()
This will initialise the value of SteamID
It's all in the error message. You can't do bitwise operations with strings, pointers to strings or anything that is not an integer, you need to convert or parse them into integers first. Use strconv.ParseInt and its friends from the strconv package to parse strings.
parsedID, e := strconv.ParseInt(*steamID, 16, 64)
if e != nil { log.Fatal("couldn't parse the ID") }
// Use parsedID.
Related
document of DnsQueryConfig here:
https://learn.microsoft.com/en-us/windows/win32/api/windns/nf-windns-dnsqueryconfig
add file dnsapi.go in project: github.com/kbinani/win, the content of the file is:
// +build windows
package win
import "unsafe"
var (
// Library
libdnsapi uintptr
// function
dnsQueryConfig uintptr
)
type DNS_CONFIG_TYPE uint32
type IP4_ARRAY struct {
AddrCount DWORD
IP4_ADDRESS [1]IP_ADDRESS_STRING
}
type PIP4_ARRAY *IP4_ARRAY
func init(){
// Library
libdnsapi = doLoadLibrary("Dnsapi.dll")
// Functions
dnsQueryConfig = doGetProcAddress(libdnsapi, "DnsQueryConfig")
}
// https://learn.microsoft.com/en-us/windows/win32/api/windns/nf-windns-dnsqueryconfig
func DnsQueryConfig(config DNS_CONFIG_TYPE, flag DWORD, pwsAdapterName PCWSTR, pReserved PVOID, pBuffer PVOID, pBufLen DWORD_PTR) int32 {
ret1 := syscall6(dnsQueryConfig,
6,
uintptr(unsafe.Pointer(&config)),
uintptr(unsafe.Pointer(&flag)),
uintptr(unsafe.Pointer(pwsAdapterName)),
uintptr(pReserved),
uintptr(pBuffer),
uintptr(unsafe.Pointer(pBufLen)),
)
return int32(ret1)
}
code in my project:
package main
import (
"fmt"
"github.com/kbinani/win"
"unsafe"
)
func main(){
// func DnsQueryConfig(config DNS_CONFIG_TYPE, flag DWORD, pwsAdapterName PCWSTR, pReserved PVOID, pBuffer PVOID, pBufLen DWORD_PTR) int32 {
config := win.DNS_CONFIG_TYPE(6)
flag := win.DWORD(0)
pwsAdapterName := win.PCWSTR(nil)
pReserved := win.PVOID(unsafe.Pointer(nil))
buffer := win.IP4_ARRAY{}
a := win.PVOID(unsafe.Pointer(&buffer))
l := uint32(unsafe.Sizeof(buffer))
pBufLen := win.DWORD_PTR(unsafe.Pointer(&l))
r := win.DnsQueryConfig(config, flag, pwsAdapterName, pReserved, a, pBufLen)
fmt.Println(r, buffer)
}
it always return code 87, can you give me some suggestions, thanks a lot.
solve the problem
package main
import (
"fmt"
"golang.org/x/sys/windows"
"net"
"strings"
"unsafe"
)
const (
DnsConfigDnsServerList int32 = 6
)
type char byte
type IpAddressString struct {
DNS [4 * 10]char
}
type Ip4Array struct {
AddrCount uint32
Ip4Address [1]IpAddressString
}
func main() {
fmt.Println(dns())
}
func dns() []string {
dns := []string{}
dnsapi := windows.NewLazyDLL("Dnsapi.dll")
dnsQuery := dnsapi.NewProc("DnsQueryConfig")
bufferBytes := make([]byte, 60)
loop:
buffer := (*Ip4Array)(unsafe.Pointer(&bufferBytes[0]))
blen := len(bufferBytes)
r1, _, _ := dnsQuery.Call(uintptr(DnsConfigDnsServerList), uintptr(0), uintptr(0), uintptr(0), uintptr(unsafe.Pointer(&bufferBytes[0])), uintptr(unsafe.Pointer(&blen)))
if r1 == 234 {
bufferBytes = make([]byte, blen)
goto loop
} else if r1 == 0 {
} else {
return dns
}
for i := uint32(1); i <= buffer.AddrCount; i++ {
right := i * 4
left := right - 4
tmpChars := buffer.Ip4Address[0].DNS[left:right]
tmpStr := []string{}
for j := 0; j < len(tmpChars); j++ {
tmpStr = append(tmpStr, fmt.Sprint(tmpChars[j]))
}
tmpDNS := strings.Join(tmpStr, ".")
pDns := net.ParseIP(tmpDNS)
if pDns == nil {
continue
}
if !pDns.IsGlobalUnicast() {
continue
}
dns = append(dns, tmpDNS)
}
return dns
}
I have a variable which value can be string or int depend on the input. I use interface{} as the type. How to convert the value of that variable to int if the input is like "50", "45", or any string of int.
package main
import "fmt"
import "log"
import "strconv"
func main() {
var limit interface{}
limit = "50"
page := 1
offset := 0
if limit != "ALL" {
log.Println("INSIDE")
offset = limit.(int)*page - limit.(int)
}
fmt.Println(offset)
}
Above code got:
interface conversion: interface {} is string, not int
If I use this:
package main
import "fmt"
import "log"
import "strconv"
func main() {
var limit interface{}
limit = "50"
page := 1
offset := 0
if limit != "ALL" {
log.Println("INSIDE")
offset = strconv.Atoi(limit)*page - strconv.Atoi(limit)
}
fmt.Println(offset)
}
I got this
exit status 2
command-line-arguments
./main.go:14:24: cannot use limit (type interface {}) as type string in argument to strconv.Atoi: need type assertion
./main.go:14:24: multiple-value strconv.Atoi() in single-value context
./main.go:14:51: cannot use limit (type interface {}) as type string in argument to strconv.Atoi: need type assertion
./main.go:14:51: multiple-value strconv.Atoi() in single-value context
How to convert value of that variable to int?
In Go, in contrast to languages such as Python/JavaScript/Perl, the variables have strict types and strong boundaries. You have to write explicit code to make the conversion of a string from/to an integer. This is helpful to write safer and more performant programs.
In addition, if the variable is stored in an interface{} you have to use a type assertion (or a type switch) to further use the content with a specific type.
Here is your fixed code:
package main
import "fmt"
import "log"
import "strconv"
func main() {
var limit interface{}
limit = "50"
page := 1
offset := 3
if limit != "ALL" {
// Type assertion
s, isString := limit.(string)
if !isString {
log.Fatalf("limit is not a string but %T", limit)
}
// Conversion from string to int, with error handling
l, err := strconv.Atoi(s)
if err != nil {
log.Fatalf("%s: %v", limit, err)
}
offset = l*page - l
}
fmt.Println(offset)
}
However, I suggest that you just use the string type for the limit variable.
strconv package can use for this kind of conversion
package main
import (
"fmt"
"strconv"
)
func main() {
var lim interface{}
lim = "10"
fmt.Printf("Type is: %T\nValue is: %s \n", lim, lim.(string))
i, _ := strconv.Atoi(lim.(string))
fmt.Printf("After conversion value is: %d", i)
}
Output of the above code:
Type is: string, Value is: 10
After conversion value is: 10
As I understood your question, value of your limit in fact is always string, but in one case it's value == ALL, otherwise it's a string representation of an integer value.
If I'm right, then I would provide following solution:
import (
"errors"
"fmt"
"strconv"
)
func getOffset(limit string, page int64) (int64, error) {
lim, err := strconv.ParseInt(limit, 10, 64)
if err != nil {
if limit == "ALL" {
return 0, nil
}
return 0, errors.New(fmt.Sprintf("string '%v' doesn't fit requirements, error: %v", limit, err))
}
offset := lim*page - lim
return offset, nil
}
Full solution on playground: https://play.golang.org/p/fJv9_cw18R5
How to get function arguments in Go at runtime, all I know is only how to get function name:
pc, file, line, ok := runtime.Caller(2)
rt := runtime.FuncForPC(pc)
return rt.Name() // Foo
What I need is something like this:
Foo(1,2,3)
// Foo_1_2_3
Not a full answer, but maybe this can help :
package main
import (
"fmt"
"reflect"
)
func main() {
fmt.Println(reflect.TypeOf(f1))
for index := 0; index < reflect.TypeOf(f1).NumIn(); index++ {
fmt.Println(reflect.TypeOf(f1).In(index))
}
}
func f1(a int, b string) {}
prints :
func(int, string)
int
string
I'm learning Golang so I can rewrite some of my shell scripts.
I have URL's that look like this:
https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value
I want to extract the following part:
https://example-1.example.com/a/c482dfad3573acff324c/list.txt
In a shell script I would do something like this:
echo "$myString" | grep -o 'http://.*.txt'
What is the best way to do the same thing in Golang, only by using the standard library?
There are a few options:
// match regexp as in question
pat := regexp.MustCompile(`https?://.*\.txt`)
s := pat.FindString(myString)
// everything before the query
s := strings.Split(myString, "?")[0] string
// same as previous, but avoids []string allocation
s := myString
if i := strings.IndexByte(s, '?'); i >= 0 {
s = s[:i]
}
// parse and clear query string
u, err := url.Parse(myString)
u.RawQuery = ""
s := u.String()
The last option is the best because it will handle all possible corner cases.
try it on the playground
you may use strings.IndexRune, strings.IndexByte, strings.Split, strings.SplitAfter, strings.FieldsFunc, url.Parse, regexp or your function.
first most simple way:
you may use i := strings.IndexRune(s, '?') or i := strings.IndexByte(s, '?') then s[:i] like this (with commented output):
package main
import "fmt"
import "strings"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
i := strings.IndexByte(s, '?')
if i != -1 {
fmt.Println(s[:i]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
}
or you may use url.Parse(s) (I'd use this):
package main
import "fmt"
import "net/url"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
url, err := url.Parse(s)
if err == nil {
url.RawQuery = ""
fmt.Println(url.String()) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
}
or you may use regexp.MustCompile(".*\\.txt"):
package main
import "fmt"
import "regexp"
var rgx = regexp.MustCompile(`.*\.txt`)
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
fmt.Println(rgx.FindString(s)) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
or you may use splits := strings.FieldsFunc(s, func(r rune) bool { return r == '?' }) then splits[0]:
package main
import "fmt"
import "strings"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
splits := strings.FieldsFunc(s, func(r rune) bool { return r == '?' })
fmt.Println(splits[0]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
you may use splits := strings.Split(s, "?") then splits[0]:
package main
import "fmt"
import "strings"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
splits := strings.Split(s, "?")
fmt.Println(splits[0]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
you may use splits := strings.SplitAfter(s, ".txt") then splits[0]:
package main
import "fmt"
import "strings"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
splits := strings.SplitAfter(s, ".txt")
fmt.Println(splits[0]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
or you may use your function (most independent way):
package main
import "fmt"
func left(s string) string {
for i, r := range s {
if r == '?' {
return s[:i]
}
}
return ""
}
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
fmt.Println(left(s)) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
If you are prosessing only URLs, you can use Go's net/url library https://golang.org/pkg/net/url/ to parse the URL, truncate the Query and Fragment parts (Query would be parm1=value,parm2=value etc.), and extract the remaining portion scheme://host/path, as in the following example (https://play.golang.org/p/Ao0jU22NyA):
package main
import (
"fmt"
"net/url"
)
func main() {
u, _ := url.Parse("https://example-1.example.com/a/b/c/list.txt?parm1=value,parm2=https%3A%2F%2Fexample.com%2Fa%3Fparm1%3Dvalue%2Cparm2%3Dvalue#somefragment")
u.RawQuery, u.Fragment = "", ""
fmt.Printf("%s\n", u)
}
Output:
https://example-1.example.com/a/b/c/list.txt
I used regexp package extract string from string .
In this example I wanted to extract between and <\PERSON> , did this by re expression and and replaced and <\PERSON> by re1 expression.
for loop used for if there there are multiple match and re1 format used for replace.
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`<PERSON>(.*?)</PERSON>`)
string_l := "java -mx500m -cp stanford-ner.jar edu.stanford.nlp.ie.crf.CRFClassifier -loadClassifier classifiers/english.all.3class.distsim.crf.ser.gz -textFile PatrickYe.txt -outputFormat inlineXML 2> /dev/null I complained to <ORGANIZATION>Microsoft</ORGANIZATION> about <PERSON>Bill Gates</PERSON>.They told me to see the mayor of <PERSON>New York</PERSON>.,"
x := re.FindAllString(string_l, -1)
fmt.Println(x)
for v,st:= range x{
re1 := regexp.MustCompile(`<(.?)PERSON>`)
y1 := re1.ReplaceAllLiteralString(st,"")
fmt.Println(v,st," : sdf : ",y1)
}
}
Play with Go
Is there a way to scan a big.Int directly from the standard input in Go? Right now I'm doing this:
package main
import (
"fmt"
"math/big"
)
func main() {
w := new(big.Int)
var s string
fmt.Scan(&s)
fmt.Sscan(s, w)
fmt.Println(w)
}
I also could have used .SetString. But, is there a way to Scan the big.Int directly from the standard input without scanning a string or an integer first?
For example,
package main
import (
"fmt"
"math/big"
)
func main() {
w := new(big.Int)
n, err := fmt.Scan(w)
fmt.Println(n, err)
fmt.Println(w.String())
}
Input (stdin):
295147905179352825857
Output (stdout):
1 <nil>
295147905179352825857
As far as I know - no, there's no other way. In fact, what you've got is the default example they have for scanning big.Int in the documentation.
package main
import (
"fmt"
"log"
"math/big"
)
func main() {
// The Scan function is rarely used directly;
// the fmt package recognizes it as an implementation of fmt.Scanner.
i := new(big.Int)
_, err := fmt.Sscan("18446744073709551617", i)
if err != nil {
log.Println("error scanning value:", err)
} else {
fmt.Println(i)
}
}
You can see the relevant section here - http://golang.org/pkg/math/big/#Int.Scan