Re: [go-nuts] When set time.Location, will be detected Data Race

2020-07-23 Thread Michael Cohen
Thanks Ian, this does not work as I mentioned because there is no way to
guarantee that my init function will run before any of my libraries
creating a time object (which many do as they start various background
tasks).

Doing what you say is fragile because even if it appears to work, one day I
might link a library and it will mysteriously break randomly (this happened
to us previously).

Is this a bug in the time package? Or simply a bug or design shortfall in
the json package? One way I thought to fix this issue is to simply fork the
json encoder and handle time.Time structs specifically, but this obviously
does not scale to eg yaml encoders etc.

Thanks
Mike

On Fri, Jul 24, 2020, 07:17 Ian Lance Taylor  wrote:

> On Thu, Jul 23, 2020 at 9:47 AM  wrote:
> >
> > A bit late to the party here but I would like to explore your rational
> for stating that time.Local should not be modified by user code. The code
> seems to suggest this is expected:
> >
> > https://golang.org/src/time/zoneinfo.go
> > ```
> >
> > // localLoc is separate so that initLocal can initialize
> > 76  // it even if a client has changed Local.
> >
> > ```
> >
> > I want to change Local because I want all JSON encoding to be normalized
> to UTC and not local time - there does not seem to be a way to do this
> (please let me know if I am missing something). It is possible to set the
> TZ env var but not from within the program itself - it has to be done via a
> hacky shell script before I launch the program. This is because it is
> impossible to guarantee that my code will run before any library might
> access any time functions causing initLocal to fire. After this changing
> the TZ env var makes no difference.
> >
> > I know I can set the Location in every time.Time object I create but
> this is impossible for time.Time objects coming from other libraries. I
> essentially need to write my own visitor to try to identify such foreign
> time.Time objects and fix their Location before they can be json serialized.
> >
> > I tried to update time.Local using atomic.SetPointer so there really is
> no race but the race detector still complains - if there a way to turn it
> off?
>
> There is no way to change time.Local.  It is accessed without any
> protection, because the time package assumes that it will not change.
>
> If your program doesn't fetch any timezones at initialization time,
> you could use
>
> func init() {
> os.Setenv("TZ", "")
> }
>
> 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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAJ%2BtYkZ%2BSASiOnm33Y9ygtfBJ0orxJquTPDx2eGvywPDzM8Gcg%40mail.gmail.com.


Re: [go-nuts] How to know if interface{} data is nil w/o reflecting?

2018-05-08 Thread Michael Cohen
Thanks Ian for the thorough explanation - again I apologize for asking noob
questions :-).

The issue in this case was this error:

panic: value method github.com/shirou/gopsutil/process.Process.String
called using nil *Process pointer

which seems to be coming from the go runtime itself. Certainly the String
method of Process does not have a pointer receiver:

func (p Process) String() string {
s, _ := json.Marshal(p)
return string(s)
}

So it makes sense for the runtime to panic when we attempt to call it on a
nil pointer. I looked at the code for the fmt.Sprintf method as you
suggested and it seems to be doing the same thing as what my code is doing
- i.e. it catches the panic and then calls reflect to check if it is
because its a nil pointer. So i guess what feels hacky is really the way it
is supposed to be done in golang.

I wrote the following code to try to understand the behavior more
https://play.golang.org/p/kKWGCeacAEM
package main

import (
"fmt"
)

func type_function(a *int) {
fmt.Println("type_function: ", a == nil)
 }

func interface_function(a interface{}) {
fmt.Println("interface_function: ", a == nil)
}

func main() {
type_function(nil)   // true
interface_function(nil)   // true

var foo *int = nil
fmt.Println("is foo nil: ", foo == nil)
interface_function(foo)  // false ... ?
}

It seems to me that if a function accepts a pointer type - it is ok to
compare a pointer type against nil. But if a function accepts an interface
as an arg it is never safe to compare an interface against nil because from
inside the function you have no idea if the caller called with actual nil,
or a variable who's value is nil (this difference is very weird because
this is not how most languages behave - a variable is usually a full
substitute to the literal value it holds).

It seems to me that the compiler should at least warn when someone is
comparing an interface to nil (or maybe the linter should warn). It does
not seem that this could ever be what you actually want and it is always a
subtle bug just waiting to bite.

Thanks
Michael.


On Wednesday, 9 May 2018, Ian Lance Taylor <i...@golang.org> wrote:

> On Tue, May 8, 2018 at 7:19 AM, Michael Cohen <scude...@gmail.com> wrote:
> >
> > Well no - the error I get is that I am attempting to call String()
> method on
> > a null receiver - so the caller just passed me a regular nil object. The
> > issue is that I am trying to make a generic polymorphic function which
> > should be able to handle whatever is thrown at it - so I guess reflect is
> > necessary.
> >
> >  I think I am supposed to detect the null receiver before calling
> String()
> > on it. I ended up using this little utility:
> >
> > https://stackoverflow.com/questions/13476349/check-for-nil-a
> nd-nil-interface-in-go
> >
> > func isNil(a interface{}) bool {
> >   defer func() { recover() }()
> >   return a == nil || reflect.ValueOf(a).IsNil()
> > }
> >
> >
> > But this feels really hacky when I really just want to say if value !=
> nil {
> > } .
>
> I think there may be some confusion here.  Go doesn't have a "regular
> nil object."  Specific types can be `nil`.  In particular, pointer
> types can be `nil`.
>
> When a type implements a `String` method it is possible to call that
> method with a `nil` pointer.  In general it is possible to call any
> method with a `nil` pointer.  That is not an error.
>
> Some specific implementations of a `String` method may panic when
> called with a `nil` pointer.  For better or for worse, the fmt package
> has special handling for this.
>
> What this means is that unless you have some special knowledge of the
> type you are working with, you should not check for `nil` before
> calling the `String` method.  For some types the `String` method will
> correctly handle `nil`.  If you have types with a `String` method that
> does not correctly handle `nil`, then it's worth pondering why and how
> you got a `nil` pointer for this type in the first place.  But if you
> can reasonably have a `nil` pointer, and can reasonably expect that
> the `String` method will panic in that case, then what you should do
> is call `fmt.Sprint(v)`.  That will do the right thing whether v's
> `String` method handles `nil` or not.
>
> 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.


Re: [go-nuts] How to know if interface{} data is nil w/o reflecting?

2018-05-08 Thread Michael Cohen
Well no - the error I get is that I am attempting to call String() method
on a null receiver - so the caller just passed me a regular nil object. The
issue is that I am trying to make a generic polymorphic function which
should be able to handle whatever is thrown at it - so I guess reflect is
necessary.

 I think I am supposed to detect the null receiver before calling String()
on it. I ended up using this little utility:

https://stackoverflow.com/questions/13476349/check-for-nil-and-nil-interface-in-go

func isNil(a interface{}) bool {
  defer func() { recover() }()
  return a == nil || reflect.ValueOf(a).IsNil()}


But this feels really hacky when I really just want to say if value != nil
{ } .

Thanks
Michael.

On Wednesday, 9 May 2018, Jakob Borg  wrote:

> On 8 May 2018, at 15:26, scude...@gmail.com wrote:
>
> But this crashes when foo is really a nil pointer to a type which does
> support Stringer.
>
>
> The crash isn’t on “your” side though, it’s presumably inside the String()
> method. Hence, the caller passed you something invalid that you can’t
> handle. I’d argue that avoiding this is their responsibility.
>
> My case is made weaker by how fmt.Println and friends handle this though.
> They’ll call the String() method, recover from the panic, use reflect to
> see if the boxed value is nil, and print a “”. I guess this is
> friendly, but not something I think normal code should do.
>
> (In your specific case you seem to be reimplementing fmt.Sprint; you can
> just use that instead. :)
>
> //jb
>

-- 
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.