Add "not null" parameter check and const variables/pointers

414 views
Skip to first unread message

aaa bbb

unread,
Mar 11, 2020, 12:49:18 AM3/11/20
to golang-nuts
I test a code in go tour, and get a nil error at first:


func say(s string, ch chan int) {
	for i := 0; i <= 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
	ch <- 1
}

func main() {
	
	//var ch chan int
	var ch chan int = make(chan int, 1)
	
	go say("world", ch)
	fmt.Println("Hello")
	<-ch
}

null reference error almost exists in every programming language.
so why not make directive that indicates a parameter is not allowed nil? like

func say(s string, ch chan int not nil) {...}

Or other more powerful validation mechanism.

-------


also, at the value receiver and pointer receiver section, sometimes we should use pointer

receiver to avoid big memory copy. This is not a good solution, maybe there should be a
const keyword that stop modification the big struct and avoid big copy.


Simple is good, but cannot too simple. CPP have a lot of good things.

Ian Lance Taylor

unread,
Mar 11, 2020, 12:57:05 AM3/11/20
to aaa bbb, golang-nuts
On Tue, Mar 10, 2020 at 9:49 PM 'aaa bbb' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> I test a code in go tour, and get a nil error at first:
>
>
> func say(s string, ch chan int) {
>
> for i := 0; i <= 5; i++ {
>
> time.Sleep(100 * time.Millisecond)
>
> fmt.Println(s)
>
> }
>
> ch <- 1
>
> }
>
>
> func main() {
>
>
>
> //var ch chan int
>
> var ch chan int = make(chan int, 1)
>
>
>
> go say("world", ch)
>
> fmt.Println("Hello")
>
> <-ch
>
> }
>
> null reference error almost exists in every programming language.
> so why not make directive that indicates a parameter is not allowed nil? like
>
> func say(s string, ch chan int not nil) {...}
>
> Or other more powerful validation mechanism.

These kinds of issues have been discussed before. See, for example,
https://golang.org/issue/30177.


> also, at the value receiver and pointer receiver section, sometimes we should use pointer
> receiver to avoid big memory copy. This is not a good solution, maybe there should be a
> const keyword that stop modification the big struct and avoid big copy.

People already have a way to avoid a big memory copy: use a pointer
receiver. It doesn't seem necessary to have a second way.

Ian

robert engels

unread,
Mar 11, 2020, 1:09:05 AM3/11/20
to Ian Lance Taylor, aaa bbb, golang-nuts
I think what the OP was trying to say, is that with ‘const’ the compiler could safely use a pointer receiver rather than a copy, and also enforce that const are not modified, and only passed as const args (may require a heap allocation though, so maybe only if struct is of a certain size based on platform/compiler opts).

I think he has a point.

When you see a ‘pointer receiver’ a developer probably assumes the code needs to modify the structs - thus you must pass a pointer. But if you are only declaring a pointer to avoid an expensive large structure copy, you are giving misleading information - and possibly causing bugs due to incorrect later code modifications.


-- 
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcXrdGyYuUvymVyPyrpUujPr5Z0%2B3cxV6tz%3DmRZkHVLisg%40mail.gmail.com.

Ian Lance Taylor

unread,
Mar 11, 2020, 1:20:18 AM3/11/20
to robert engels, aaa bbb, golang-nuts
On Tue, Mar 10, 2020 at 10:08 PM robert engels <ren...@ix.netcom.com> wrote:
>
> I think what the OP was trying to say, is that with ‘const’ the compiler could safely use a pointer receiver rather than a copy, and also enforce that const are not modified, and only passed as const args (may require a heap allocation though, so maybe only if struct is of a certain size based on platform/compiler opts).
>
> I think he has a point.
>
> When you see a ‘pointer receiver’ a developer probably assumes the code needs to modify the structs - thus you must pass a pointer. But if you are only declaring a pointer to avoid an expensive large structure copy, you are giving misleading information - and possibly causing bugs due to incorrect later code modifications.

Thanks. I don't see how to make that work, though. Consider

type S struct { a [10000]byte }

func (s const S) PrintLater() {
go func() {
time.Sleep(time.Second)
fmt.Printf("%s\n", s.a)
}()
}

func F() {
var s S
s.a[0] = 'a'
s.PrintLater()
s.a[0] = 'b'
}

With a value receiver the behavior is straightforward. With a pointer
receiver this is a race condition. With a const receiver, what is it?
It shouldn't be a race; after all, we've promised that the const
receiver won't modify the receiver. So we have to copy the struct.

Ian

Robert Engels

unread,
Mar 11, 2020, 2:07:12 AM3/11/20
to Ian Lance Taylor, aaa bbb, golang-nuts
True. But in the current situation, if the object was large, you either do a copy (bad) or use a pointer and synchronize (worse?) - or you have to be sequential.

So, const could also carry with it sequential requirements (prohibited to be captured by a Go routine), or alternatively, if captured a copy is made at the time of capture (so you only pay the copy penalty in this case)

If you need to be concurrent and pass pointers around for performance you need synchronized access anyway - so you are probably adding an access layer anyway.

To the OPs point, the “when to use a pointer receiver” in Go has always struck me as a bit “loose” and in the wild many times creates either performance issues or race conditions. Something like this might tighten it up a bit.



> On Mar 11, 2020, at 12:20 AM, Ian Lance Taylor <ia...@golang.org> wrote:

Robert Engels

unread,
Mar 11, 2020, 9:50:33 AM3/11/20
to Ian Lance Taylor, aaa bbb, golang-nuts
Thinking about this over morning coffee it is more complex. It is not just sequential consistency that affects it - placing the struct in a map or some other reference container would also have to force a copy.

Less and less utility.

> On Mar 11, 2020, at 3:33 AM, Robert Engels <ren...@ix.netcom.com> wrote:
>
> True. But in the current situation, if the object was large, you either do a copy (bad) or use a pointer and synchronize (worse?) - or you have to be sequential.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/C0AED78A-1473-44F5-B3F4-0015DB7608C2%40ix.netcom.com.

Reply all
Reply to author
Forward
0 new messages