[go-nuts] How to use map to manage channel correctly?

2019-01-17 Thread Fei Ding
Hi

I met a panic() when trying to manage channal by dict, as

map[string]chan int

I can understand that the map forbids concurrent read/write, but in my 
case, it actually forbid concurrent r/w to the channel, which is the basic 
operation.
So how to implement this request correctly?

The panic is something like:

goroutine 1661 [running]:
runtime.throw(0x59de0d, 0x21)
/usr/local/go/src/runtime/panic.go:619 +0x81 fp=0xc420045ed8 
sp=0xc420045eb8 pc=0x42a501
runtime.mapaccess1_faststr(0x564e40, 0xc42008aba0, 0xc4200ceba0, 0x10, 
0xc4200a2f48)
/usr/local/go/src/runtime/hashmap_fast.go:181 +0x421 fp=0xc420045f48 
sp=0xc420045ed8 pc=0x40be31

And the  throw is:

throw("concurrent map read and map write")



-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[go-nuts] Where is the very first g/m/p?

2018-11-19 Thread Fei Ding
Hi

I am trying to figure out the process of creation of the very first 
g(goroutine), together with the very fist m, and p. It seems that the 
deepest code I can find is at proc.go 
, and 
the getg() function is my dead end, which has no implementation written by 
golang. So, here is my q:

1. I guess before the user main() function be executed, a lot of work has 
already been finished, including creating the very first g/m/p, where the 
code is? It seems to be asm code? I do have some problem reading/digging 
asm code.

2. Could any one explain the whole process of creating the very first g/m/p?

Thanks.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [go-nuts] different way to malloc memory when creating channel

2018-10-21 Thread Fei Ding
Thanks for the clarification.

On Mon, Oct 22, 2018 at 13:13 Ian Lance Taylor  wrote:

> On Sun, Oct 21, 2018 at 8:34 PM, Fei Ding  wrote:
> >
> > I am studying golang source code, literally `go/src/runtime/chan.go`, the
> > question is in function `makechan`, when it comes to malloc memory for
> > channel with/without pointers, you guys did it as:
> >
> >
> > case elem.kind != 0:
> > // Elements do not contain pointers.
> > // Allocate hchan and buf in one call.
> > c = (*hchan)(mallocgc(hchanSize+uintptr(size)*elem.size, nil, true))
> > c.buf = add(unsafe.Pointer(c), hchanSize)
> > default:
> > // Elements contain pointers.
> > c = new(hchan)
> > c.buf = mallocgc(uintptr(size)*elem.size, elem, true)
> >
> > So, my question is why to use two different ways to do this, (continuous
> vs
> > separated) ? and what's the difference/relationship between malloc and
> new?
>
> The hchan struct is designed so that it doesn't contain any pointers
> that the garbage collector needs to know about, as explained in the
> comment a few lines above the code you quote.  If the channel elements
> don't contain any pointers, then the garbage collector doesn't have to
> scan them.  So in that case we can allocate a single large block of
> memory to hold the hchan struct and the channel buffer, and the
> garbage collector will never to scan that large buffer.  That tends to
> give better memory cache behavior and slightly lessens the load on the
> garbage collector.  When the channel elements do have pointers, we
> allocate the channel buffer separately, as that is easier than
> building up a GC structure that handles both the hchan struct and the
> buffer.  The key difference is that in the no-pointer case we pass nil
> as the type argument to mallocgc, and in the pointer case we pass the
> element type.
>
> Calling new is equivalent to calling mallocgc(sizeof_type, type,
> true).  The only reason to call mallocgc is when the runtime wants to
> vary one of those arguments.
>
> Ian
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[go-nuts] different way to malloc memory when creating channel

2018-10-21 Thread Fei Ding
Hi

I am studying golang source code, literally `go/src/runtime/chan.go`, the 
question is in function `makechan`, when it comes to malloc memory for 
channel with/without pointers, you guys did it as:


case elem.kind != 0:
// Elements do not contain pointers.
// Allocate hchan and buf in one call.
c = (*hchan)(mallocgc(hchanSize+uintptr(size)*elem.size, nil, true))
c.buf = add(unsafe.Pointer(c), hchanSize)
default:
// Elements contain pointers.
c = new(hchan)
c.buf = mallocgc(uintptr(size)*elem.size, elem, true)

So, my question is why to use two different ways to do this, (continuous vs 
separated) ? and what's the difference/relationship between malloc and new?

Thanks.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[go-nuts] what's the difference between Golang and Java about interface?

2016-10-08 Thread Fei Ding


Recently I've been asked a question which is, what's the difference between 
Golang and Java about *interface*?


I know there are some 'syntax-sugar level' differences, what I am 
interested is anything beneath the ground, like how does Golang and Java 
implement interface? What's the biggest difference? Which one is more 
efficient? Why?


Could anyone post blog links or source code about this topic? The only code 
I can find is in src/runtime/iface.go, but I cannot understand it or get 
anything useful by myself yet. Source code is better.


Thanks.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [go-nuts] differences between pointer and value slice in for-range loop

2016-09-18 Thread Fei Ding
Thanks, Marvin, I've learned a lot from your reply. And, I've written more
code, like:

a, b, c := 1, 2, 3
> slice1 := []int{a, b, c}
> for _, n := range slice1 {
> go func(n *int) {fmt.Println(*n)}()
> }


 It seems that pass *n's address *in the code above will make a data race,
which you have already explained why. But still, I have another question:
If the coder do really want the addresses of elements in slice, how to do
it correctly?

Thanks.



2016-09-18 2:03 GMT+08:00 Marvin Renich <m...@renich.org>:

> * Fei Ding <fding...@gmail.com> [160916 23:30]:
> > Link here: https://play.golang.org/p/cdryPmyWt5
> >
> > The code above is going to check the differences between pointers and
> > values in a for loop, while go statement is also used at the same time.
> For
> > code:
> >
> > values := []field{{"one"},{"two"},{"three"}}
> > for _, v := range values {
> > go v.print()
> > }
> >
> > we know that the console will print *three three three* as result,
> because
> > for loop runs into its end before go routines start executing, which
> write
> > *v* as the last element of the slice. But what about pointers?
> >
> > poniters := []*field{{"one"},{"two"},{"three"}}
> > for _, v := range poniters {
> > go v.print()
> > }
> >
> > It seems to print* one two three*, why?
>
> Try running your example with the race detector.  Then try commenting
> out, on separate trials, each of the two cases, again running under the
> race detector.
>
> The second case runs without a race, but the first does not.
>
> To understand why, you must carefully analyze what is happening
> according to the Go specification
> (https://golang.org/ref/spec#Go_statements).
>
> In the both cases, the variable v is reused for all iterations of the
> for loop; that is, every iteration of the loop uses the same variable v,
> but with a different value for each iteration.
>
> Now, in the first case, v is of type field.  The go statement evaluates
> the function value and parameters.  Evaluating the function value means,
> essentially, getting a pointer to the function to be called (this is a
> simplification, but is accurate enough for this analysis); it does not
> yet call the function.
>
> A method call can be thought of as a function call with the receiver as
> an implied first argument.  So the first, implied, argument is evaluated
> as  (because, according to the spec, x.m() is shorthand for ().m()
> in this scenario).  The go statement creates a new goroutine with this
> particular function call, with the address of v as the first argument,
> to be executed at the go scheduler's discretion.
>
> Next, the for loop assigns the next element from the slice values to the
> variable v.  This is the data race.  There is no guarantee that the
> scheduler will wait for the sleep statement after the loop to start
> executing the first goroutine, and in fact it didn't on one run on my
> system; I got a result of two three three.  There is no synchronization
> between the assignment to v by the for loop and the reference of v.name
> in v.print, so you have a data race.
>
> In the second case, v is of type *field.  The go statement evaluates the
> first, implied, argument as the current value of v (the first pointer in
> the slice).  The go statement creates a goroutine with a call to the
> print method with that value as the argument.
>
> When the for loop assigns the next element from the slice to v, it is
> not changing anything that is being referenced by the go routine, so
> there is no data race (and the values printed are taken from successive
> slice elements).
>
> ...Marvin
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "golang-nuts" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/
> topic/golang-nuts/yxhNl3Rnl6Y/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[go-nuts] differences between pointer and value slice in for-range loop

2016-09-16 Thread Fei Ding
Hi:

Please check this code snippet:

package main

import (  
"fmt"
"time"
)

type field struct {  
name string
}

func (p *field) print() {  
fmt.Println(p.name)
}

func main() {
fmt.Println("use values:")

// use values in range loop and go rountines
values := []field{{"one"},{"two"},{"three"}}
for _, v := range values {
go v.print()
}

time.Sleep(time.Second)

fmt.Println()
fmt.Println("use pointers:")

// use pointers in range loop and go rountines
poniters := []*field{{"one"},{"two"},{"three"}}
for _, v := range poniters {
go v.print()
}

time.Sleep(time.Second)
}

Link here: https://play.golang.org/p/cdryPmyWt5

The code above is going to check the differences between pointers and 
values in a for loop, while go statement is also used at the same time. For 
code:

values := []field{{"one"},{"two"},{"three"}}
for _, v := range values {
go v.print()
}

we know that the console will print *three three three* as result, because 
for loop runs into its end before go routines start executing, which write 
*v* as the last element of the slice. But what about pointers? 

poniters := []*field{{"one"},{"two"},{"three"}}
for _, v := range poniters {
go v.print()
}

It seems to print* one two three*, why?

Thanks.







-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [go-nuts] How Golang implements slice?

2016-09-13 Thread Fei Ding
Thanks, Edward, you make a good point.

What's more, I wrote more code yesterday, and found that we can in fact get
the 4th element even if the descriptor tells us there are only 3, by
using package
unsafe <https://golang.org/pkg/unsafe/>, and doing some simple pointer
calculation. It shows that function calls may modify the slice in
parameters under the cover, which is a bad thing if it is not on purpose. I
will keep this in mind.

Thanks.




2016-09-13 12:09 GMT+08:00 Edward Muller <edwar...@interlix.com>:

>
>
> On Mon, Sep 12, 2016 at 8:17 PM Fei Ding <fding...@gmail.com> wrote:
>
>> Hi guys:
>>
>> I met a problem when I try to understand slice when using as function
>> parameters. After writing some code, I made a conclusion by myself, but
>> need some real check and explanation here, with your help.
>>
>> As far as I know, Golang's function parameters are passed by value, and
>> slice could be treated as a descriptor, which seems like *{pointer to
>> first element of underlying array, length of element, capacity of array}*
>> according to Go Slices: usage and internals
>> <https://blog.golang.org/go-slices-usage-and-internals>. So, can I say:
>>
>> *When passing a slice as a function parameter, it is, in fact, passing a
>> pointer, and two int values (or as a whole struct, or maybe more parameters
>> to describe the slice, whatever).*
>>
>> To make it clear using code:
>>
>> func foo(s []T) {...}
>> // can this function be treated as following 3-parameter function?
>> func foo(p Pointer, length, capa int) {...}
>>
>> // Note: type is not the point here,
>> //   and we just need 3 parameters, while there maybe more
>>
>> You may wonder why I have this question? Here is where everything started:
>>
>> func foo(s []int) {
>>  s := []int{1,2,3}
>>  foo(s)
>>  fmt.Println(s)
>> }
>>
>> Everyone know it will print [1 2 3], not [1 2 3 100]. But what I am
>> interested in, is *whether the function call does modify the memory*
>> just after the tail of element 3, to an int of 100. If my assumption above
>> is right, then the modification may happen.
>>
>> So, I made some experiments.
>>
>> package main
>>
>> import "fmt"
>> import "strconv"
>>
>> type Node struct {
>> val int
>> left *Node
>> right *Node
>> }
>>
>> func (n Node) String () string {
>> return strconv.Itoa(n.val)
>> }
>>
>> func newNode(val int) *Node {
>> return {val, nil, nil}
>> }
>>
>> // Given a binary tree and a target sum, find all root-to-leaf paths
>> // where each path's sum equals the given sum
>> func bs(root *Node, path []*Node, now int, target int, ret *[][]*Node) {
>> if root == nil {
>> return
>> }
>> path = append(path, root)
>> now += root.val
>> if now == target && root.left == nil && root.right == nil {
>> *ret = append(*ret, path)
>> return
>> }
>> bs(root.left, path, now, target, ret)
>> bs(root.right, path, now, target, ret)
>> }
>>
>> func main() {
>> // a simple tree like:
>> //0
>> //   / \
>> //  1   2
>> root := newNode(0)
>> left := newNode(1)
>> right := newNode(2)
>> root.left = left
>> root.right = right
>>
>> ret := [][]*Node{}
>> bs(root, make([]*Node, 0, 10), 0, 1, )
>> fmt.Println(ret)
>> }
>>
>>
>> As the code above, it is a function to find all root-to-leaf paths where
>> each path's sum equals the given sum in a binary tree, and, I make a simple
>> test case which there are only 3 nodes: one root, two children, with values
>> of 0, 1 and 2.
>>
>> Say, I want to find the paths of sum of 1. So, I call this function as:
>>
>> bs(root, make([]*Node, 0, 10), 0, 1, )
>>
>> It is petty common to make a guess that, this call will give us a final
>> result of [0, 1], which is obviously the correct answer, however, it gives
>> us [0, 2], try yourself if you don't believe:
>>
>> https://play.golang.org/p/hSKIOaVK2S
>>
>> The algorithm here is correct, don't worry about it. Instead, please pay
>> attention to the second parameter of bs(). It makes a slice which has no
>> element in it, and has a capacity of 10. What if we change this parameter
>> to:
>>
>> bs(root, make([]*Node, 0, 1), 0, 1, )
>>
>> Yes, just make the slice's capacity as 1. This time you will get the
>> right answer, [0, 1]. Try yourself if you are interested.
>>
>> Here i