I'm trying to integrate cobra in my program - go

I was referring to spf13/cobra.
I downloaded the cobra package using go get github.com/spf13/cobra/cobra and imported "github.com/spf13/cobra" in my program and then installed it using go install github.com/spf13/cobra/cobra.
This is my program - It is a calculator which can be implemented of number of inputs , but for now only 2 are taken from the user. I wanted to use cobra in this program.
package main
import (
"fmt"
"github.com/spf13/cobra"
)
func add(m ...int) int {
sum := 0
for _, a := range m {
sum += a
}
return sum
}
func sub(m ...int) int {
sub := m[0]
for _, a := range m[1:] {
sub -= a
}
return sub
}
func mul(m ...float32) float32 {
pro := float32(1)
for _, a := range m {
pro *= a
}
return pro
}
func div(m ...float32) float32 {
quo := m[0]
for _, a := range m[1:] {
quo /= a
}
return quo
}
var i int
func display() {
fmt.Println("Choose the operation : 1:Addition 2:Subtration 3:Multiplication 4:Division ")
fmt.Scanln(&i)
}
func main() {
display()
var v1,v2 int
fmt.Println("Enter 2 numbers with enter")
fmt.Scanln(&v1)
fmt.Scanln(&v2)
switch i {
case 1:
fmt.Println(add(v1,v2))
case 2:
fmt.Println(sub(v1,v2))
case 3:
fmt.Println(mul(float32(v1),float32(v2)))
case 4:
fmt.Println(div(float32(v1),float32(v2)))
}
}

You need to run go get github.com/spf13/cobra/cobra first. go install can only install packages you've already downloaded, go get downloads and installs a package.

Related

Zone method from time package doesn't return updated timezone if timezone is changed during process execution

I have written below a simple Go code to get the system timezone. It works fine and returns the system's current timezone. The issue is if I change the timezone in-between process execution then it doesn't return the updated timezone. It returns only the old timezone.
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 10; i++ {
t := time.Now()
zone, offset := t.Zone()
fmt.Println(zone, offset)
z, _ := t.Zone()
fmt.Println("timezone", z)
}
}
if you have a look at the source code of the time package, you can find that the local Location is set once at the start of the application, by a sync.Once (or more precisely: when the tz information is obtained by a call to .get() for the first time):
// localLoc is separate so that initLocal can initialize
// it even if a client has changed Local.
var localLoc Location
var localOnce sync.Once
func (l *Location) get() *Location {
if l == nil {
return &utcLoc
}
if l == &localLoc {
localOnce.Do(initLocal)
}
return l
}
Now, initLocal is platform-dependent since different platforms handle time zones differently; for example for Windows you have:
func initLocal() {
var i syscall.Timezoneinformation
if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
localLoc.name = "UTC"
return
}
initLocalFromTZI(&i)
}
From here on, you could work your way through the source code to get an idea how you can implement this for your application. For example on Windows, you could get the UTC offset in minutes by calling the Bias and DaylightBias fields of the syscall.Timezoneinformation struct.
Thanks, #MrFuppes
The issue got resolved by calling Win32 API from Golang. Below is the code snippet.
package main
import (
"fmt"
"time"
"syscall"
"strconv"
"unicode/utf16"
)
func main() {
for index := 0; index < 10; index++ {
now := time.Now()
timeZone, _ := now.Zone()
fmt.Println("timezone", timeZone)
var itz syscall.Timezoneinformation
if _, err := syscall.GetTimeZoneInformation(&itz); err != nil {
fmt.Println("GetTimeZoneInformation failed")
}
fmt.Println(strconv.Itoa(int(itz.Bias)))
var newBytes []uint16
const intBits = 4 + 4*(^uint(0)>>63)
if intBits == 4 {
//For 32 bit
bytes := itz.StandardName
for i := 0; i < len(bytes); i++ {
c := bytes[i]
if c == 0 {
break
}
newBytes = append(newBytes, c)
}
} else if intBits == 8 {
//For 64 bit
bytes := itz.StandardName
for i := 0; ; i++ {
c := bytes[i]
if c == 0 || i == 2048 {
break
}
newBytes = append(newBytes, c)
}
}
tzName := string(utf16.Decode(newBytes))
fmt.Println("Timezone StandardName: ", tzName)
}
}

How set process to a CPU using Go in windows?

I want set a process to a CPU using Go in win7, the below code:
package main
import (
"fmt"
"math"
"runtime"
"syscall"
"unsafe"
)
func SetAffinity(pid int, mask *int64) {
syscall.Syscall(syscall.SYS_SCHED_SETAFFINITY,
uintptr(pid), 8, uintptr(unsafe.Pointer(mask)))
}
func GetAffinity(pid int, mask *int64) {
syscall.Syscall(syscall.SYS_SCHED_GETAFFINITY,
uintptr(pid), 8, uintptr(unsafe.Pointer(mask)))
}
var cpuNum = float64(runtime.NumCPU())
var setx = []struct {
args int
expected int64
}{
{0, int64(math.Pow(2, cpuNum)) - 2},
}
func main() {
for _, ca := range setx {
var cpuSet int64
GetAffinity(ca.args, &cpuSet)
cpuSet = cpuSet & 0XFFFFFFE
SetAffinity(ca.args, &cpuSet)
fmt.Println(cpuSet)
GetAffinity(ca.args, &cpuSet)
fmt.Println(cpuSet)
}
}
When I use go run affinity.go, get the follow info:
# command-line-arguments
.\affinity.go:12: undefined: syscall.SYS_SCHED_SETAFFINITY
.\affinity.go:13: not enough arguments in call to syscall.Syscall
.\affinity.go:17: undefined: syscall.SYS_SCHED_GETAFFINITY
.\affinity.go:18: not enough arguments in call to syscall.Syscall
I find SYS_SCHED_SETAFFINITY that it only used in linux.
So, I want to set a process to a cpu using Go in Windows(Win7), what can I do?
You'll have to invoke the WinAPI SetProcessAffinityMask.
Something like this should work:
func setProcessAffinityMask(h syscall.Handle, mask uintptr) (err error) {
r1, _, e1 := syscall.Syscall(syscall.NewLazyDLL("kernel32.dll").NewProc("SetProcessAffinityMask").Addr(), 2, uintptr(h), mask, 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
h being the process handle, and mask being the desired affinity mask, of course.
This is taken from Go benchmarks, under the BSD license.

Accessing a benchmark's result

I've seen there is a struct testing.BenchmarkResult in Go to accesss the result of a benchmark but I found very little documentation or examples to help me use it.
So far I have only been benchmarking my functions like this:
func BenchmarkMyFunction(b *testing.B) {
// call to myFunction
}
And then running:
go test -bench=".*"
Here the results are printed to the console but I'd like to store them in a separate file. How can I use the BenchmarkResult type to do this?
For example:
package main
import (
"fmt"
"testing"
"time"
)
func Add(a, b int) int {
time.Sleep(10 * time.Microsecond) // Just to make the test take some time
return a + b
}
func BenchAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = Add(1, 2)
}
}
func main() {
res := testing.Benchmark(BenchAdd)
fmt.Printf("%s\n%#[1]v\n", res)
}
Produces:
120000 10000 ns/op
testing.BenchmarkResult{N:120000, T:1200000000, Bytes:0, MemAllocs:0x0, MemBytes:0x0, Extra:map[string]float64{}}
Playground.
You can easily write these results out to a file using ioutil.WriteFile.
Playground w/ WriteFile.

How to access a capturing group from regexp.ReplaceAllFunc?

How can I access a capture group from inside ReplaceAllFunc()?
package main
import (
"fmt"
"regexp"
)
func main() {
body := []byte("Visit this page: [PageName]")
search := regexp.MustCompile("\\[([a-zA-Z]+)\\]")
body = search.ReplaceAllFunc(body, func(s []byte) []byte {
// How can I access the capture group here?
})
fmt.Println(string(body))
}
The goal is to replace [PageName] with PageName.
This is the last task under the "Other tasks" section at the bottom of the Writing Web Applications Go tutorial.
I agree that having access to capture group while inside of your function would be ideal, I don't think it's possible with regexp.ReplaceAllFunc.
Only thing that comes to my mind right now regard how to do this with that function is this:
package main
import (
"fmt"
"regexp"
)
func main() {
body := []byte("Visit this page: [PageName] [OtherPageName]")
search := regexp.MustCompile("\\[[a-zA-Z]+\\]")
body = search.ReplaceAllFunc(body, func(s []byte) []byte {
m := string(s[1 : len(s)-1])
return []byte("" + m + "")
})
fmt.Println(string(body))
}
EDIT
There is one other way I know how to do what you want. First thing you need to know is that you can specify non capturing group using syntax (?:re) where re is your regular expression. This is not essential, but will reduce number of not interesting matches.
Next thing to know is regexp.FindAllSubmatcheIndex. It will return slice of slices, where each internal slice represents ranges of all submatches for given matching of regexp.
Having this two things, you can construct somewhat generic solution:
package main
import (
"fmt"
"regexp"
)
func ReplaceAllSubmatchFunc(re *regexp.Regexp, b []byte, f func(s []byte) []byte) []byte {
idxs := re.FindAllSubmatchIndex(b, -1)
if len(idxs) == 0 {
return b
}
l := len(idxs)
ret := append([]byte{}, b[:idxs[0][0]]...)
for i, pair := range idxs {
// replace internal submatch with result of user supplied function
ret = append(ret, f(b[pair[2]:pair[3]])...)
if i+1 < l {
ret = append(ret, b[pair[1]:idxs[i+1][0]]...)
}
}
ret = append(ret, b[idxs[len(idxs)-1][1]:]...)
return ret
}
func main() {
body := []byte("Visit this page: [PageName] [OtherPageName][XYZ] [XY]")
search := regexp.MustCompile("(?:\\[)([a-zA-Z]+)(?:\\])")
body = ReplaceAllSubmatchFunc(search, body, func(s []byte) []byte {
m := string(s)
return []byte("" + m + "")
})
fmt.Println(string(body))
}
If you want to get group in ReplaceAllFunc, you can use ReplaceAllString to get the subgroup.
package main
import (
"fmt"
"regexp"
)
func main() {
body := []byte("Visit this page: [PageName]")
search := regexp.MustCompile("\\[([a-zA-Z]+)\\]")
body = search.ReplaceAllFunc(body, func(s []byte) []byte {
// How can I access the capture group here?
group := search.ReplaceAllString(string(s), `$1`)
fmt.Println(group)
// handle group as you wish
newGroup := "<a href='/view/" + group + "'>" + group + "</a>"
return []byte(newGroup)
})
fmt.Println(string(body))
}
And when there are many groups, you are able to get each group by this way, then handle each group and return desirable value.
You have to call ReplaceAllFunc first and within the function call FindStringSubmatch on the same regex again. Like:
func (p parser) substituteEnvVars(data []byte) ([]byte, error) {
var err error
substituted := p.envVarPattern.ReplaceAllFunc(data, func(matched []byte) []byte {
varName := p.envVarPattern.FindStringSubmatch(string(matched))[1]
value := os.Getenv(varName)
if len(value) == 0 {
log.Printf("Fatal error substituting environment variable %s\n", varName)
}
return []byte(value)
});
return substituted, err
}

Remove multiple items from a slice

I am trying to remove multiple items from a slice by using the Delete examples from here: http://code.google.com/p/go-wiki/wiki/SliceTricks
Here is the code I have:
package main
import "fmt"
import "net"
func main() {
a := []string{"72.14.191.202", "69.164.200.202", "72.14.180.202", "2600:3c00::22", "2600:3c00::32", "2600:3c00::12"}
fmt.Println(a)
for index, element := range a {
if net.ParseIP(element).To4() == nil {
//a = append(a[:index], a[index+1:]...)
a = a[:index+copy(a[index:], a[index+1:])]
}
}
fmt.Println(a)
}
While the code works fine if I have only one IPv6 address in the slice, it fails if there are more than one IPv6 address. It fails with the error "panic: runtime error: slice bounds out of range". What should I do to fix this code so it's able to delete all IPv6 addresses?
Your problem is that you are modifying the slice that you are iterating over. Below is your code a bit modified:
package main
import (
"fmt"
"net"
)
func main() {
a := []string{"72.14.191.202", "69.164.200.202", "72.14.180.202", "2600:3c00::22", "2600:3c00::32", "2600:3c00::12"}
fmt.Println(a)
for i := 0; i < len(a); i++ {
if net.ParseIP(a[i]).To4() == nil {
a = append(a[:i], a[i+1:]...)
//a = a[:i+copy(a[i:], a[i+1:])]
i-- // Since we just deleted a[i], we must redo that index
}
}
fmt.Println(a)
}
Playground
Just to raise the point : it is always tricky to alter the structure on which you are iterating.
A common way to avoid this is to build the end result in a new variable :
package main
import (
"fmt"
"net"
)
func main() {
a := []string{"72.14.191.202", "69.164.200.202", "72.14.180.202", "2600:3c00::22", "2600:3c00::32", "2600:3c00::12"}
fmt.Println(a)
var b []string
for _, ip := range a {
if net.ParseIP(ip).To4() != nil {
b = append(b, ip)
}
}
fmt.Println(b)
}
http://play.golang.org/p/7CLMPw_FQi

Resources