Convert array of strings to field name - go

Newbie question:
I want to print various variables of a library (is that the correct name? reflect.TypeOf(servers) gives []lib.Server)
I want to do something like this, but this obviously does not work:
servers, err := GetClient().GetServers() //call to external API
serverVariables := []string{}
serverVariables = append(serverVariables, "Name")
serverVariables = append(serverVariables, "IPAddress")
for _, server := range servers {
for _,element := range serverVariables {
fmt.Println(server.element)
}
}
What I already can do is the following (but I want to do it using the above approach):
servers, err := GetClient().GetServers() //call to external API
for _, server := range servers {
fmt.Println(server.Name)
fmt.Println(server.IPAddress)
}
giving the following output:
ServerNameOne
192.168.0.1
ServerNameTwo
192.168.0.2

Reflection is what you probably want to use:
for _, server := range servers {
v := reflect.ValueOf(server)
for _, element := range serverVariables {
fmt.Println(v.FieldByName(element))
}
}
You should also change serverVariables initialization to be serverVariables := []string{}
Playground example: https://play.golang.org/p/s_kzIJ7-B7
It seems to me that you have experience in some dynamic language like Python or JavaScript. Go is compiled and strongly typed. Besides reflection being slower, when using it compiler can't help you with finding basic errors in your code and what is most important you lose type of the accessed variable.
More info on http://blog.golang.org/laws-of-reflection
So I strongly recommend you to keep your current approach:
for _, server := range servers {
fmt.Println(server.Name)
fmt.Println(server.IPAddress)
}

Related

How to use Golang to get my wifi ip address?

func getLocalIP() ([]string, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
IPs := make([]string, 0)
for _, a := range addrs {
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
IPs = append(IPs, ipNet.IP.To4().String())
}
}
}
return IPs, nil
}
func TestGetLocalIP() {
addrs, _ := getLocalIP()
for _, a := range addrs {
fmt.Println(a)
}
}
I used this,but it give me a list of ip address.
I just want to get my wifi local address,how to do that?
You need to know at least one of two pieces of information going in:
the name of the correct interface (typically en0 on a Mac, e.g., but YMMV)
the address for your wireless network, including the length of the mask - something like 192.168.0.0/16 or 192.168.0.0/24 is pretty common, but you'll have to figure this out ahead of time.
If you only know the interface name:
ifs, _ := net.Interfaces()
for _, ifi := range ifs {
if ifi.Name == "en0" { // Or whatever other filter you want
addrs, _ := ifi.Addresses()
for _, a := range addrs {
// Filter to get the one you want, typically unicast IP4
}
}
}
Still simpler:
if, _ := net.InterfaceByName("en0")
addrs, _ := if.Addresses()
for _, a := range addrs {
// As before, filter for the address you want
}
If you know the network address for your wireless network
// Loop over interfaces, get addrs, then loop over addresses and get IPs for those that have them
if ip.Mask(net.CIDRMask(16, 32)) == myNetworkAddress {
// The interface you got this IP from is probably your wifi interface
}
Which method to choose
Depending on the interface having a specific name is generally not going to be portable. So while my assumption was that you were just trying to get this working on your own workstation, if this is for something which needs to run across multiple hosts, you may need to start off at least with matching against the correct network address. There are other tricks as well - if you know e.g. that you are going to be running in a server farm in which every host has a NIC from manufacturer XXX, you can look up the MAC address and see if it comes from that manufacturer - you can try this out here. You can use other filters as well, but those are going to be pretty specific to your individual use case.

given apiversion and kind how do i find if resource is namespaced scoped or not using client go

given apiversion=v1 and kind=Secret how do i find if this resource(Secret) is Namespaced or not in golang
I know how to get all api-resources and then i can filter desired resource like so
client, _ := kubernetes.NewForConfig(config)
res, _ := discovery.ServerPreferredResources(client.Discovery())
for _, resList := range res {
for _, r := range resList.APIResources {
fmt.Println(r.Kind, "\t", r.Namespaced)
}
}
but i only want fetch for particular resource. is it possible?

unstructured.UnstructuredList caused lots of reflect.go trace

I'm trying to use the unstructured.UnstructuredList to reuse come logic for configmap and secret.
However, after adding the ListAndDeployReferredObject, I started to see tons of trace as Starting reflector *unstructured.Unstructured was added to my log file.
Am I doing something odd or I'm missing some setting for using the unstructured.Unstructured?
Thanks in advance.
func (r *ReconcileSubscription) ListAndDeployReferredObject(instance *appv1alpha1.Subscription, gvk schema.GroupVersionKind, refObj referredObject) error {
insName := instance.GetName()
insNs := instance.GetNamespace()
uObjList := &unstructured.UnstructuredList{}
uObjList.SetGroupVersionKind(gvk)
opts := &client.ListOptions{Namespace: insNs}
err := r.Client.List(context.TODO(), uObjList, opts)
if err != nil && !errors.IsNotFound(err) {
klog.Errorf("Failed to list referred objects with error %v ", err)
return err
}
// other logics...
}
I0326 23:05:58.955589 95169 reflector.go:120] Starting reflector *unstructured.Unstructured (10m0s) from pkg/mod/k8s.io/client-go#v0.0.0-20191016111102-bec269661e48/tools/cache/reflector.go:96
...
I0326 23:15:18.718932 95169 reflector.go:158] Listing and watching *unstructured.Unstructured from pkg/mod/k8s.io/client-go#v0.0.0-20191016111102-bec269661e48/tools/cache/reflector.go:96
I figured out these prints are normal, since we are using the dynamic client on our controller for caches

golang net module(LookupSRV)

I'm very new to golang, I have some experience with python but not on this level per say. I am creating an application that's called "digall", making it easy for a user to see active dns-records when checking a domain name.
In the application I am using LookupSRV, which I seem to have some issues with:
func srvRecord(query string) {
service := "sipfederationtls"
protocol:= "tcp"
fmt.Printf("\n[+] SRV Record(s)\n")
//srvMap := ["sipfederationtls", "autodiscover", "VLMCS"]
cname, addresses, err := net.LookupSRV(service, protocol, query)
if err != nil {
fmt.Printf("[!] This feature is currently under development, thus not ready yet.\n")
}
fmt.Printf("cname : %s \n", cname)
for i := 0; i < len(addresses); i++ {
fmt.Printf("addrs[%d].Target : %s \n", i, addresses[i].Target)
fmt.Printf("addrs[%d].Port : %d \n", i, addresses[i].Port)
fmt.Printf("addrs[%d].Priority : %d \n", i, addresses[i].Priority)
fmt.Printf("addrs[%d].Weight : %d \n", i, addresses[i].Weight)
}
}
As you can see the variable "service" serves as the prefix of the SRV record. My only problem is that i want to check multiple prefixes of this record, namely "sipfederationtls", "autodiscover" and "VLMCS".
What I am asking is; How to i make this function swift through these prefixes and return the ones that work? (the ones that error out will be handled by err by my fantastic error message)
I am aware that this is a noob question, and like I said I am very new to golang. I would appreciate any tips you guys could give me.
Here is the full source of the application: http://dpaste.com/3X24ZYR
Thank you.
You can't query multiple services at once using LookupSRV method, as you can't use dig for querying several services at once.
You better create a slice of the services' names:
services := [...]string{"service1", "service2", "service3")
And then iterate over it and call LookupSRV for each service:
for _, service := range services {
cname , addrs, err := net.LookupSRV(service, "tcp", "your.domain.name")
// error handlling
}
Also when iterating over the lookup result, it is better to use the range keyword:
for _, record := range addrs {
fmt.Printf("Target: %s:%d\n", record.Target, record.Port)
}

How to use parse many times in golang's template

i need help. Now to output pages I use multiple templates(1 example) and i want to use parse many times in one template(2 example)
Example 1:
...
t, err := template.ParseFiles("header.html")
t.Execute(wr, data)
d, err := template.ParseFiles("content.html")
d.Execute(wr, datatwo)
...
Example 2:
...
t := template.New("blabla")
t.ParseFiles("header.html")
t.ParseFiles("content.html")
t.Execute("wr", data)
P.S. I'm sorry, my english is very bad
template.ParseFiles can take multiple filenames as an argument, as per http://golang.org/pkg/html/template/#ParseFiles
func ParseFiles(filenames ...string) (*Template, error)
e.g.
t := template.New("base")
t, err := t.ParseFiles("header.html", "footer.html", "content.html")
if err != nil {
// handle the error
}
There's a solid example on how to use html/template in the Go docs as well: http://golang.org/doc/articles/wiki/#tmp_6

Resources