I am trying to populate a map based on output from various goroutines. For this I have created a channel of type (map[key][]int)
done := make(chan map[int][]int)
and pass it to workers goroutine, along with the key value, which is int for the example.
for i := 0; i < 10; i++ {
go worker(i, done)
}
I want to populate my map as I read from the key. Currently I am doing as below
for i := 0; i < 10; i++ {
m := <-done
fmt.Println(m)
for k,v := range m {
retmap[k] = v
}
}
fmt.Println(retmap)
I feel I am not doing this correctly. Is there a better way to do this using channels? Any suggestions would be much appreciated?
playground: https://play.golang.org/p/sv4Qk4hEljx
You could use a specific channel per worker instead of encoding that information in the result object of the worker. Something like:
func worker(done chan []int) {
fmt.Print("working...")
rnd := rand.Intn(10)
fmt.Println("Sleeping for ", rnd, "seconds")
for i := 0; i < rnd; i++ {
time.Sleep(time.Second)
}
fmt.Println("done")
// Send a value to notify that we're done.
done <- makeRange(0, rnd)
}
func main() {
channels := make([]chan []int, 10, 10)
for i := 0; i < 10; i++ {
channels[i] = make(chan []int)
go worker(channels[i])
}
retmap := make(map[int][]int)
for i := 0; i < 10; i++ {
retmap[i] = <-channels[i]
}
fmt.Println(retmap)
}
Playground link
Related
There is a function that sets a pointer to a nil value:
func nilSetter(x *int) {
x = nil
}
I have such snippet of code:
i := 42
fmt.Println(&i)
nilSetter(&i)
fmt.Println(&i)
Which prints:
0xc42008a000
0xc42008a000
While I expect:
0xc42008a000
nil
I know that it happens because function nilSetter just copy address and sets to nil that copy.
But how can I do it correctly?
The only way to achieve that is with a pointer to a pointer. And it's pretty clunky so it's probably not what you want:
func nilSetter(x **int) {
*x = nil
}
func main() {
x := 2
xp := &x
fmt.Println(xp)
nilSetter(&xp)
fmt.Println(xp)
}
// Output:
// 0x10414020
// <nil>
The reason of such behaviour is because there is no pass by reference in Go.
Two variables can have contents that point to the same storage location. But, it is not possible to have them share the same storage location.
Example:
package main
import "fmt"
func main() {
var a int
var b, c = &a, &a
fmt.Println(b, c) // 0x1040a124 0x1040a124
fmt.Println(&b, &c) // 0x1040c108 0x1040c110
}
From your code, the argument x of nilSetter is pointing to some location but it have its own address and when you are setting a nil to it, you are changing its address not the address of what it is pointing to.
package main
import "fmt"
func nilSetter(x *int) {
x = nil
fmt.Println(x, &x) // <nil> 0x1040c140
}
func main() {
i := 42
fmt.Println(&i) // 0x10414020
nilSetter(&i)
fmt.Println(&i) // 0x10414020
}
That is why pointers always have an exact address even its value is nil
Referencing to a blog post by Dave Cheney: https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go
Just use return value and assign.
func nilSetter(x *int) *int {
x = nil
return x
}
x = nilSetter(x)
int rtadd(IPaddr net, IPaddr mask, IPaddr gw, unsigned metric)
{
struct route *prt, *srt, *prev;
srt= malloc(sizeof(struct route));
bool isdup;
int hv = 0, i = 0;
if (!Route.ri_valid)
rtinit();
prt = rtnew(net, mask, gw, metric);
prt->rt_key = 0;
for (i - 0; i < 32; ++i)
prt->rt_key += (mask >> i) & 1;
prev = NULL;
hv = rthash(net);
isdup = false;
for (srt = rttable[hv]; srt; srt = srt->rt_next) //trouble point (issue with srt = rttable[hv])?
{
if (prt->rt_key > srt->rt_key)
{
break;
}
if (srt->rt_net == prt->rt_net && srt->rt_mask == prt->rt_mask)
{
isdup = true;
break;
}
prev = srt;
}
return 0;
}
In the above code I created a pointer srt and used a malloc command to initialize it. When I assign it to the array rttable which is declared as struct route *rttable[RT_TSIZE];, the srt pointer becomes NULL. What could be causing this?
The code which is being done for a project in my networking class is based off of Douglas Comer's TCP/IP volume II book:
https://www.amazon.com/Internetworking-TCP-Vol-Implementation-Internals/dp/0139738436
The malloc is now a memory leak since you are not actually using that allocated memory address. In your for loop, you are re-assigning your src pointer to a different location in memory by pointing it to rttable[hv]. So, if you examined rttable[hv] you will most likely find it's value set to 0 or null.
guys! I am a beginner in Go. I have some doubts When I learning reflect package ,here's the code:
package main
import (
"encoding/json"
"fmt"
"reflect"
)
func checkError(err error) {
if err != nil {
panic(err)
}
}
type Test struct {
X int
Y string
}
func main() {
fmt.Println("hello world!")
test1()
test2()
}
func test1() {
a := Test{}
fmt.Printf("a: %v %T \n", a, a)
fmt.Println(a)
err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), &a)
checkError(err)
fmt.Printf("a: %v %T \n", a, a)
}
func test2() {
fmt.Println("===========================")
m := make(map[string]reflect.Type)
m["test"] = reflect.TypeOf(Test{})
a := reflect.New(m["test"]).Elem().Interface()
fmt.Printf("a: %v %T \n", a, a)
fmt.Println(a)
err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), &a)
checkError(err)
fmt.Printf("a: %v %T \n", a, a)
}
and the result :
a: {0 } main.Test
{0 }
a: {1 x} main.Test
===========================
a: {0 } main.Test
{0 }
a: map[X:1 Y:x] map[string]interface {}
Why these two way make different result, Could anyone tell me why, many thanks.
In test2 you're passing in the address of the interface{} containing a Test value. When the value is dereferenced by the json package it only sees an interface{}, and therefor it unmarshals into the default types.
What you need is an interface{} containing a pointer to a Test value.
// reflect.New is creating a *Test{} value.
// You don't want to dereference that with Elem()
a := reflect.New(m["test"]).Interface()
// 'a' contains a *Test value. You already have a pointer, and you
// don't want the address of the interface value.
err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), a)
I use the following Go code to get some info about the network interfaces. Any suggestions on how I would be able to get the status of promiscuous mode for each interface?
type Iface struct {
Name string `json:"name"`
Status string `json:"status"`
Multicast bool `json:"multicast"`
Broadcast bool `json:"broadcast"`
}
func (c *InterfacesController) GetInterfaces() {
interfaces, err := net.Interfaces()
if err != nil {
fmt.Println(err)
return
}
var ifaceset []Iface
var ifc Iface
for _, i := range interfaces {
ifc.Name = i.Name
if strings.Contains(i.Flags.String(), "up") {
ifc.Status = "UP"
} else {
ifc.Status = "DOWN"
}
if strings.Contains(i.Flags.String(), "multicast") {
ifc.Multicast = true
} else {
ifc.Multicast = false
}
if strings.Contains(i.Flags.String(), "broadcast") {
ifc.Broadcast = true
} else {
ifc.Broadcast = false
}
ifaceset = append(ifaceset, ifc)
}
}
It doesn't appear Go has a cross-platform way of checking the PROMISC flag (I can't even find out for sure if such a flag exists for windows.) Here is a way to get it on linux, which I'm guessing you're on:
package main
import (
"fmt"
"net"
"os"
"syscall"
"unsafe"
)
func GetPromiscuous(i net.Interface) (bool, error) {
tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
if err != nil {
return false, os.NewSyscallError("netlinkrib", err)
}
msgs, err := syscall.ParseNetlinkMessage(tab)
if err != nil {
return false, os.NewSyscallError("parsenetlinkmessage", err)
}
loop:
for _, m := range msgs {
switch m.Header.Type {
case syscall.NLMSG_DONE:
break loop
case syscall.RTM_NEWLINK:
ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
if ifim.Index == int32(i.Index) {
return (ifim.Flags & syscall.IFF_PROMISC) != 0, nil
}
}
}
return false, os.ErrNotExist
}
func main() {
ints, err := net.Interfaces()
if err != nil {
panic(err)
}
for _, i := range ints {
p, err := GetPromiscuous(i)
if err != nil {
panic(err)
}
fmt.Println(i.Name, p)
}
}
This is based of the interfaceTable function in the standard library. It uses rtnetlink to get the flags of the interface. Unless you want to roll your own syscall.NetlinkRIB function, this code will always pull the information for every network device and filter out the requested one.
A bit less magical way to get the flag you want is to use cgo and ioctl:
package main
/*
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
bool is_promisc(char *name) {
int s = socket(AF_INET, SOCK_STREAM, 0);
struct ifreq *i = malloc(sizeof *i);
strncpy((char *)&(i->ifr_name), name, IFNAMSIZ);
ioctl(s, SIOCGIFFLAGS, i);
bool p = (i->ifr_flags & IFF_PROMISC) != 0;
free(i);
return p;
}
*/
import "C"
import (
"fmt"
"net"
)
func GetPromiscuous(i net.Interface) (bool, error) {
set, err := C.is_promisc(C.CString(i.Name))
return bool(set), err
}
func main() {
ints, err := net.Interfaces()
if err != nil {
panic(err)
}
for _, i := range ints {
p, err := GetPromiscuous(i)
if err != nil {
panic(err)
}
fmt.Println(i.Name, p)
}
}
A final note is that either way may not always tell you correctly whether an interface is actually in promiscuous mode or not. See this thread for more details.
From what I'm reading using the netlink route should work correctly, but another post says we should be checking the promiscuous count. Please let me know if someone knows how to do that, because I can't find how to. The only stackoverflow question on the matter has gone unanswered.
I think either of these methods will work as long as you're not doing any crazy networking stuff (bridge, vlan interfaces, macvtap, etc.) The code definitely works if you use iproute2 tools to turn promisc on and off on an interface.
The working environment is Ubuntu, I used the ifconfig command and checked each interface details to see if it contains the word PROMISC. Something like this:
//
// get the interfaces
//
interfaces, err := net.Interfaces()
//
// run the ifconfig command
//
out, err := exec.Command("/bin/sh", "-c", "ifconfig").Output()
var ifc Iface
var ifaceset []Iface
//
// split the output to handle each interface separately
//
var ifaceDetails = strings.Split(string(out), "\n\n")
//
// iterate interfaces
//
for _, i := range interfaces {
ifc.Name = i.Name
if strings.Contains(i.Flags.String(), "up") {
ifc.Status = "UP"
} else {
ifc.Status = "DOWN"
}
if strings.Contains(i.Flags.String(), "multicast") {
ifc.Multicast = true
} else {
ifc.Multicast = false
}
if strings.Contains(i.Flags.String(), "broadcast") {
ifc.Broadcast = true
} else {
ifc.Broadcast = false
}
//
// try to find the word PROMISC to check if it is UP
//
for _, ifdetails := range ifaceDetails {
if strings.Contains(ifdetails, i.Name) {
if strings.Contains(ifdetails, "PROMISC") {
ifc.Promisc = true
} else {
ifc.Promisc = false
}
}
}
ifaceset = append(ifaceset, ifc)
}
}
I am trying to create a simple program to test semaphores. I am forking the process and tormenting the value of variable c in the critical section of each process, but the value of c I get is still 1 not 2. Even with the mmap() uncommented. Can anyone please explain to me what I am doing wrong? Any help would be appreciated. I am a total newbie in this. Thank you very much for your time.
int main()
{
int c = 0;
sem_t mutex;
sem_t mutex1;
// sem_t *mutex = (sem_t*)mmap(NULL, sizeof(sem_t*), PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1, 0);
sem_init(&mutex, 0, 1);
sem_init(&mutex1, 0, 1);
pid_t i;
int id = fork();
if(id == -1) {}
else if(id == 0)
{
sem_wait (&mutex);
c++;
sem_post (&mutex);
}
else
{
sem_wait (&mutex);
c++;
sem_post (&mutex);
}
cout<<c<<endl;
//system("pause");
return 0;
}
I tried it another way by making the pshared argument 1, but it still does not work.
I have also tried it sem_op but it still does not work.
int main()
{
int c = 0;
int sid =semget(1105,2, 0666 | IPC_CREAT);
pid_t i;
int id = fork();
if(id == -1)
{
}
else if(id == 0)
{
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = 0;
if((semop(sid, &sb, 1)) == -1)
cout<<"error"<<endl;
c++;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = 0;
if((semop(sid, &sb, 1)) == -1)
cout<<"error"<<endl;
}
else if(id == 1)
{
struct sembuf sb;
if((semop(sid, &sb, 1)) == -1)
cout<<"error"<<endl;
c++;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = 0;
if((semop(sid, &sb, 1)) == -1)
cout<<"error"<<endl;
}
cout<<c<<endl;
return 0;
}
If you use fork() you have to share the semaphores between the forked processes. See sem_init() manual for more details.
Alternatively you can use a named semaphore, see sem_open() for details, and
also a good article on the subject.
Your primary misstep is that the variable c is not itself shared — each process operates on its own copy of the variable. You want something like this:
int *c;
c = mmap(NULL, sizeof(*c), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
*c = 0;
// ... later ...
++*c;
Additionally, with respect to your sem_init() example, you should:
Allocate shared memory of the correct size: sizeof(sem_t) and not sizeof(sem_t*)
Set the pshared flag during sem_init()
You likely don't need conditional logic differentiating parent from child after the fork(). After all, you want them to do the same thing.
(Separately, please do not name a POSIX semaphore "mutex." That name will mislead hurried, POSIXly-minded folk who will think you are referring to a different kind of synchronization primitive.)
With respect to your semget() example, you appear to be waiting on the semaphore twice (sb.sem_op = -1) in the child process. The post-fork() check for the parent is incorrect — you check if the returned PID is 1 (which it will never be on a typical UNIX system) rather than if the returned PID is > 0. (Again, however, you likely don't need to have parent and child do different things here.)