package main
import (
"fmt"
"reflect"
)
type Aservice struct {
}
type Adata struct {
msg string
}
type Bdata struct {
more string
}
var amap map[string]interface{} = make(map[string]interface{}, 1024)
func (aser *Aservice) Bar(data *Adata) error {
return nil
}
func (aser *Aservice) Foo(data *Bdata) error {
return nil
}
func main() {
var ser *Aservice
typeOfService := reflect.TypeOf(ser)
valueOfService := reflect.ValueOf(ser)
for i := 0; i < valueOfService.NumMethod(); i++ {
nref := valueOfService.Method(i).Type().In(0)
fmt.Println("++", nref.Elem().Name())
amap[typeOfService.Method(i).Name] = nref
}
}
Currently "Adata" and "Bdata" can be printed correctly
But I don’t know how to store the empty structure pointers of "Adata" and "Bdata" in amap
No idea for the next step
I want to use Method(i).Name() in amap to store the parameters that need to be passed in for the Method
Based on the suggestions in comments :
package main
import (
"fmt"
"reflect"
)
type Aservice struct {
}
type Adata struct {
msg string
}
type Bdata struct {
more string
}
var amap = map[string]interface{}{}
func (aser *Aservice) Bar(data *Adata) error {
return nil
}
func (aser *Aservice) Foo(data *Bdata) error {
return nil
}
func main() {
var ser *Aservice
typeOfService := reflect.TypeOf(ser)
valueOfService := reflect.ValueOf(ser)
for i := 0; i < valueOfService.NumMethod(); i++ {
nref := valueOfService.Method(i).Type().In(0)
amap[typeOfService.Method(i).Name] = reflect.New(nref.Elem()).Interface()
}
for k, v := range amap {
fmt.Printf("%s %#v\n", k, v)
}
}
Output:
Bar &main.Adata{msg:""}
Foo &main.Bdata{more:""}
package main
import "fmt"
func main() {
var kata, kosong, kebalikan string
fmt.Print("Kata :")
fmt.Scan(&kata)
panjang := len(kata)
for i := panjang - 1; i >= 0; i-- {
kebalikan := kosong + fmt.Print(string(kata[i]))
}
if kata == kebalikan {
fmt.Println("\n", true)
} else {
fmt.Println("\n", false)
}
}
does anybody know how to store kosong + fmt.Print(string(kata[i])) to kebalikan ? just new in golang
the error is multiple-value fmt.Print() in single-value context
There are two problems with your code.
You need to use fmt.Sprint instead of fmt.Print in your case. The former returns a string, the latter prints it to stdout.
Do not use : in kebalikan := kosong + fmt.Print(string(kata[i])). You do not want to create a new local variable, instead modify the existing variable.
Here is the fixed code:
package main
import "fmt"
func main() {
var kata, kosong, kebalikan string
fmt.Print("Kata :")
fmt.Scan(&kata)
panjang := len(kata)
for i := panjang - 1; i >= 0; i-- {
kebalikan = kosong + fmt.Sprint(string(kata[i]))
}
if kata == kebalikan {
fmt.Println("\n", true)
} else {
fmt.Println("\n", false)
}
}
I got a interface with more than one method. I wonder how to write a middleware for it.
I seek in Google but found all the answers are for interface with only one method. I found nothing for my problem. And I try to write a demo, but it does not work.
package main
import (
"fmt"
"strconv"
)
type ti interface {
Say(int) string
Eat(string) int
}
type Middleware func(ti) ti
func GetMiddleWare(t ti) ti {
var tm ti
t.Say = func(i int) string {
fmt.Println("arg is " + strconv.Itoa(i))
var ret string
defer func() {
fmt.Println("ret is " + ret)
}()
ret = t.Say(i)
return ret
}
t.Eat = func(s string) int {
fmt.Println("arg is " + s)
var ret int
defer func() {
fmt.Println("ret is " + strconv.Itoa(ret))
}()
ret = t.Eat(s)
return ret
}
return tm
}
it does not work
.\main.go:17:8: cannot assign to t.Say
.\main.go:26:8: cannot assign to t.Eat
So, how can I write a middleware for an interface with more than one method?
Define a type that wraps the value. Implement the interface methods on that type.
// Middleware wraps the value t with logging.
type Middleware struct {
t ti
}
func (m Middleware) Say(i int) string {
fmt.Println("arg is " + strconv.Itoa(i))
var ret string
defer func() {
fmt.Println("ret is " + ret)
}()
ret = m.t.Say(i)
return ret
}
func (m Middleware) Eat(s string) int {
fmt.Println("arg is " + s)
var ret int
defer func() {
fmt.Println("ret is " + strconv.Itoa(ret))
}()
ret = m.t.Eat(s)
return ret
}
func GetMiddleWare(t ti) ti {
return Middleware{t}
}
I'm trying to use the govmomi library (https://github.com/vmware/govmomi) to make some automated changes to a VM but I can't seem to get around the nil pointer exceptions on line 134 and 136 for the last few hours. I got it to work at one point but then I'm not sure what I'm doing wrong now as I've tried so many combos but nothing seems to work now...
package main
import (
"context"
"flag"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
"net/url"
"os"
"strings"
"fmt"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
"log"
)
type change struct {
*flags.VirtualMachineFlag
}
const (
envURL = "GOVC_URL"
envUserName = "GOVC_USERNAME"
envPassword = "GOVC_PASSWORD"
envInsecure = "GOVC_INSECURE"
)
// getEnvString returns string from environment variable.
func getEnvString(v string, def string) string {
r := os.Getenv(v)
if r == "" {
return def
}
return r
}
// getEnvBool returns boolean from environment variable.
func getEnvBool(v string, def bool) bool {
r := os.Getenv(v)
if r == "" {
return def
}
switch strings.ToLower(r[0:1]) {
case "t", "y", "1":
return true
}
return false
}
var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
var urlFlag = flag.String("url", getEnvString(envURL, "https://username:password#host"+vim25.Path), urlDescription)
var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
var insecureFlag = flag.Bool("insecure", getEnvBool(envInsecure, false), insecureDescription)
func processOverride(u *url.URL) {
envUsername := os.Getenv(envUserName)
envPassword := os.Getenv(envPassword)
// Override username if provided
if envUsername != "" {
var password string
var ok bool
if u.User != nil {
password, ok = u.User.Password()
}
if ok {
u.User = url.UserPassword(envUsername, password)
} else {
u.User = url.User(envUsername)
}
}
// Override password if provided
if envPassword != "" {
var username string
if u.User != nil {
username = u.User.Username()
}
u.User = url.UserPassword(username, envPassword)
}
}
func NewClient(ctx context.Context) (*govmomi.Client, error) {
flag.Parse()
// Parse URL from string
u, err := soap.ParseURL(*urlFlag)
if err != nil {
return nil, err
}
// Override username and/or password as required
processOverride(u)
// Connect and log in to ESX or vCenter
return govmomi.NewClient(ctx, u, *insecureFlag)
}
func main() {
ctx := context.Background()
// Connect and login to ESX or vCenter
c, err := NewClient(ctx)
if err != nil {
log.Fatal(err)
}
defer c.Logout(ctx)
var spec *types.VirtualMachineConfigSpec
var cmd *change
var flip bool
flip = false
spec.VPMCEnabled = &flip
vm, err := cmd.VirtualMachine()
task, err := vm.Reconfigure(ctx, *spec)
if err != nil {
println(err)
}
fmt.Println(task.Wait(ctx))
}
the 2 lines that are throwing errors are:
spec.VPMCEnabled = &flip
and
vm, err := cmd.VirtualMachine()
both seem to throw the same panic: runtime error: invalid memory address or nil pointer dereference. If I comment out the first one throwing the error, the second one throws it then.
I think both are unrelated but I can't quite figure how how to do the dereferencing correctly.
----UPDATE EDIT 1--------------
I made some changes to this with the below response but still can't get around the error on at task, err := vm.Reconfigure(ctx, *spec)...
package main
import (
"context"
"flag"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
"net/url"
"os"
"strings"
"fmt"
"github.com/vmware/govmomi/vim25/types"
"log"
)
const (
envURL = "GOVC_URL"
envUserName = "GOVC_USERNAME"
envPassword = "GOVC_PASSWORD"
envInsecure = "GOVC_INSECURE"
)
// getEnvString returns string from environment variable.
func getEnvString(v string, def string) string {
r := os.Getenv(v)
if r == "" {
return def
}
return r
}
// getEnvBool returns boolean from environment variable.
func getEnvBool(v string, def bool) bool {
r := os.Getenv(v)
if r == "" {
return def
}
switch strings.ToLower(r[0:1]) {
case "t", "y", "1":
return true
}
return false
}
var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
var urlFlag = flag.String("url", getEnvString(envURL, "https://username:password#host"+vim25.Path), urlDescription)
var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
var insecureFlag = flag.Bool("insecure", getEnvBool(envInsecure, false), insecureDescription)
func processOverride(u *url.URL) {
envUsername := os.Getenv(envUserName)
envPassword := os.Getenv(envPassword)
// Override username if provided
if envUsername != "" {
var password string
var ok bool
if u.User != nil {
password, ok = u.User.Password()
}
if ok {
u.User = url.UserPassword(envUsername, password)
} else {
u.User = url.User(envUsername)
}
}
// Override password if provided
if envPassword != "" {
var username string
if u.User != nil {
username = u.User.Username()
}
u.User = url.UserPassword(username, envPassword)
}
}
func NewClient(ctx context.Context) (*govmomi.Client, error) {
flag.Parse()
// Parse URL from string
u, err := soap.ParseURL(*urlFlag)
if err != nil {
return nil, err
}
// Override username and/or password as required
processOverride(u)
// Connect and log in to ESX or vCenter
return govmomi.NewClient(ctx, u, *insecureFlag)
}
func main() {
ctx := context.Background()
// Connect and login to ESX or vCenter
c, err := NewClient(ctx)
if err != nil {
log.Fatal(err)
}
defer c.Logout(ctx)
var spec *types.VirtualMachineConfigSpec
spec = new(types.VirtualMachineConfigSpec)
var flip bool
flip = false
spec.VPMCEnabled = &flip
var vm *object.VirtualMachine
vm = new(object.VirtualMachine)
task, err := vm.Reconfigure(ctx, *spec)
if err != nil {
println(err)
}
fmt.Println(task.Wait(ctx))
}
the full error I'm getting is this:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x280 pc=0x14e18f6]
goroutine 1 [running]:
github.com/vmware/govmomi/vim25.(*Client).RoundTrip(0x0, 0x1886f00, 0xc000016088, 0x1884140, 0xc000298720, 0x1884140, 0xc000298740, 0x300, 0x16e8ac0)
/Users/ronakpatel/go/src/github.com/vmware/govmomi/vim25/client.go:89 +0x26
github.com/vmware/govmomi/vim25/methods.ReconfigVM_Task(0x1886f00, 0xc000016088, 0x1884060, 0x0, 0xc0002d0000, 0xc000288000, 0xc000080400, 0x0)
/Users/ronakpatel/go/src/github.com/vmware/govmomi/vim25/methods/methods.go:10879 +0xb8
github.com/vmware/govmomi/object.VirtualMachine.Reconfigure(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1886f00, 0xc000016088, 0x0, ...)
/Users/ronakpatel/go/src/github.com/vmware/govmomi/object/virtual_machine.go:207 +0x19b
main.main()
/Users/ronakpatel/go/src/awesomeProject1/main.go:143 +0x1ec
exit status 2
----UPDATE EDIT 2----------
I changed somethings around and used the answer provided below but now I'm getting the error again but at this part: task, err := vm.Reconfigure(ctx, spec1)
Error:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x153d05a]
goroutine 1 [running]:
main.main()
/Users/ronakpatel/go/src/awesomeProject1/main.go:134 +0x19a
exit status 2
Code:
spec1 := types.VirtualMachineConfigSpec{
VPMCEnabled: &[]bool{false}[0],
}
var vm *object.VirtualMachine
var vmf *flags.VirtualMachineFlag
vmf, ctx = flags.NewVirtualMachineFlag(ctx)
vm, _ = vmf.VirtualMachine()
task, err := vm.Reconfigure(ctx, spec1)
if err != nil {
println(err)
}
fmt.Println(task.Wait(ctx))
var spec *types.VirtualMachineConfigSpec // error: spec is nil pointer
spec = new(types.VirtualMachineConfigSpec) // fix: spec is not nil
var cmd *change
var flip bool
flip = false
// used here
spec.VPMCEnabled = &flip
vm, err := cmd.VirtualMachine()
I have a problem with making dynamic model of a struct. I mean that I want to assert or cast, or just change the type of struct according to the incoming data strut.
if sourceName variable would be type_x , than the type of deserializedData should be type_x, if type_y, than type_y. How to set the variable deserializedData dynamicly for this ?
I have this part in my code:
....
var cacheData []byte
var deserializedData models.NoaggModel
cache_err := cache.Get(string(string(sourceName) + "_" + string(t.Date)), &cacheData);
if cache_err != nil {
fmt.Println("cache_error: ", cache_err)
panic("the cache is empty")
}
err2 := json.Unmarshal([]byte(cacheData), &deserializedData)
if err2 == nil {
fmt.Println("deserialized data: " + string(sourceName), deserializedData)
}
for _, chart := range charts {
w.Name = chart.Name
if err2 == nil {
w.Data = countDataByName(sourceName, deserializedData, t.Request.Filters, string(chart.Name))
}
out <- w
}
....
How to modify it, to avoid setting models.Noagg Model type in a strict way?
Creating an instance of a type dynamically during runtime can be done using the reflect package. You can use a map to store the different types that you should be able to create:
Example:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
Foo string
}
type Bar struct {
Bar int
}
func main() {
var sourceTypes = map[string]reflect.Type{
"foo": reflect.TypeOf(Foo{}),
"bar": reflect.TypeOf(Bar{}),
}
sourceName := "foo"
var deserializedData interface{}
deserializedData = reflect.New(sourceTypes[sourceName]).Interface()
fmt.Printf("%#v", deserializedData)
}
Output:
&main.Foo{Foo:""}
Playground: http://play.golang.org/p/qeDA4cu5et