Re: [go-nuts] Need help to close/shutdown http server when underlying socket fd explicitly bind used

2024-02-16 Thread Reto
On Thu, Feb 15, 2024 at 11:30:53AM -0800, Bing wrote:
> I'm trying to implement a http server and I need to bind the underlying 
> socket to a specific VRF instance so that the server only listens on that 
> VRF instance. When some specific event happens, the program needs to 
> shutdown the http server. I'm using syscall.SetsockoptString() and option 
> "SO_BINDTODEVICE".

Pretty sure what you are doing doesn't make sense... aren't you hooking into
the wrong timing?

You need to set the socket option prior to binding, not after.
There's a more convenient interface with a syscall.RawConn than what you are
using.
The attached mod seems to work, maybe try that?

Cheers,
Reto

-- 
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/h36frmpo4ecm337q7zphdqyr4aydg6fdn642gl4fpigoychuwf%40kewug6kxb2li.
package main

import (
"context"
"errors"
"fmt"
"net"
"net/http"
"syscall"
"time"
)

func main() {
// Generate a self-signed certificate and private key
// Create a TCP listener
listenConf := net.ListenConfig{
Control: func(_ string, _ string, c syscall.RawConn) error {
var err error
cerr := c.Control(func(fd uintptr) {
err = syscall.SetsockoptString(int(fd), 
syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, "eth0")
})
return errors.Join(cerr, err)
},
}
listener, err := listenConf.Listen(context.Background(), "tcp", 
"localhost:443")
if err != nil {
fmt.Println("Error creating listener:", err)
return
}
// Create an HTTP server with the custom listener and TLS config
server := &http.Server{
Addr:"localhost:443",
Handler: http.HandlerFunc(handler),
}

// Start the HTTP server
go func() {
fmt.Println("Starting HTTP server with TLS...")
if err := server.Serve(listener); err != nil && err != 
http.ErrServerClosed {
fmt.Println("Error starting server:", err)
return
}
}()

// Start a timer
duration := 1 * time.Second
fmt.Printf("Timer started. Server will be closed after %s.\n", duration)
timer := time.NewTimer(duration)

// Wait for the timer to expire
<-timer.C

// Close the HTTP server gracefully
fmt.Println("Closing HTTP server...")
if err := server.Close(); err != nil {
fmt.Println("Error closing server:", err)
return
}

fmt.Println("HTTP server closed.")
}

// Handler for incoming requests
func handler(w http.ResponseWriter, _ *http.Request) {
fmt.Fprintf(w, "Hello, HTTPS!")
}


[go-nuts] Re: Trying to understand aversion to main package

2024-02-16 Thread Marcello H
My main acts just like a mini bootstrap to do as less as possible and hand 
the real action over to start.Run()
But is is still testable.

```

var mainRunner = runner

/* -- Methods/Functions -- */

// runner starts the application and can be overwritten in a test for 
mocking.
func runner() error {
return start.Run() //nolint:wrapcheck // not needed here
}

/*
main is the bootstrap of the application.
*/
func main() {
err := mainRunner()
if err != nil {
fmt.Println("Error:\n", libErrors.GetError(err))
}
}
```
In an internal test, the mainRunner is mocked and can emulate an error if 
needed.
func Test_Main_Error(t *testing.T) {
mainRunner = func() error {
return errors.New("test error")
}

defer func() {
mainRunner = runner
}()

captured := libCapture.Direct(func() {
main()
})

assert.Contains(t, captured, "test error")
}

Op donderdag 15 februari 2024 om 10:05:11 UTC+1 schreef Brian Candler:

> On Thursday 15 February 2024 at 00:08:44 UTC Jerry Londergaard wrote:
>
> If code is outside of the main function but still in the main package, it 
> seems its testable like other functions?
>
>
> Yes indeed.
>  
>
> I suspect though if one is putting tests in package main_test, then I 
> guess you can't import the main package to test it :(
>
>
> Works fine as far as I can see:
> https://go.dev/play/p/7UtYP2j8hg6
>
> (Tests don't run in the playground, unless you explicitly invoke a runner, 
> but you can run this locally to demonstrate)
>

-- 
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/83536ffc-8a80-4fbb-8a26-8dafe2b764e5n%40googlegroups.com.


[go-nuts] Could we trade all the `ctx context.Context` arguments for one pointer in `g`?

2024-02-16 Thread Sam Vilain

Hi all,

Many moons ago I wrote a proposal 
 
to make /execution context/ a fundamental concept in Go, effectively 
moving `context.Context` to being part of the language, not just an 
extension.


The main reason to do this is that then it would not be up to the source 
maintainer to have to do the refactoring it takes to retrofit `ctx 
context.Context` arguments passed to functions as the first position, as 
has become the common boilerplate.  In some places, this is impossible: 
for instance, the io.Reader and related interfaces forbid a 
`context.Context` argument, so a reader cannot know where it is being 
read from.


Why does that matter, you might ask?  The main reason is for 
observability: tracing, logging, debugging, etc.  Of course, context 
should in general not be used to alter behavior, but for observability, 
it seems like it would be fair game for the append–only map that 
`Context` provides, to be available even when working with less than 
stellar code.


I'm wondering how people would feel about this now?

A summary of my original proposal would be to add a "soft" keyword 
("context") which is only meaningful when used before "var", but would 
not be prohibited from being a variable name.  I did some 
experimentation with the go parser and found I could get code with 
'context' added to is passing the parsing tests, so I'm pretty sure this 
would work without slowing things down.  That's the syntax I'll use in 
this message, but of course this is subject to feedback and taste.


Some basic principles stated as text for discussion; there are code 
examples in the original proposal from August 2017.


 * Semantically, creating a new scope creates a new execution context. 
   Hopefully that is a tautology.
 * Context Variables can be declared in any execution context, using
   `context var` instead of plain `var`, and assuming the `context var`
   is in scope of the observer, to all execution scopes created from
   that execution context, including goroutines.
 * The reverse is not true: the only way you can see changes to a
   variable declared in a high level context, is if the variable has a
   pointer, and the sub–level context changes it (i.e., there's no
   "magic const effect" of declaring a variable with context var.)
 * Functions that don't declare context variables use the same context
   as their caller for retrieving context variables.
 o Declaring it without assigning it in a function allows you to
   read it, without changing the context.  Like other variables
   declared without an assignment, reading it from a context with
   no parent context that has assigned it would reveal the zero value.
 o You can refer to the old value in the rvalue of the declaration,
   or at any point from when you declare it to when you assign it
   within a function.  However, having an assignment in the scope
   should be thought of creating a new context immediately with an
   implicit assignment at the declaration.  I think this behavior
   keeps the semantics as unambiguous as possible, and avoids
   having to do funny stuff when assigning the variable late in a
   function.
 * Scope would work differently.  While the /state/ of the value
   follows the execution context, the visibility of the variable would
   be defined by (a) the package the variable is declared in, and (b)
   the Case of the variable.
 o `context var localInfo` can only be read and written in the
   package it is declared in.
 o While reading the rest of this, be careful not to think of the
   Monty Python Spam song, as this is about Spans, which are not
   the same.
 o `context var OpenSpan Span` declares an exported context
   variable, which can be accessed as below:
 o declaring `context var tracing.OpenSpan` would mean to access
   the `OpenSpan` context variable exported by the `tracing`
   package.  This would only be a compile error if the `tracing`
   package has no `context var OpenSpan x` statement in it.
 + Simply /reading /the context variable from outside the
   package might not need a special syntax:
   `(tracing.OpenSpan)` to read it might work just fine, to
   allow eg:
   `tracing.OpenSpan.Log("happening", tracing.Tag("id", id))`
 o Finally, `context var tracing.OpenSpan =
   tracing.OpenSpan.New("canBeSlowFunc", tracing.InternalKind,
   ...)` is an example of how you could work with the exported
   context variables from a package.  The example there is an
   idiomatic way for a function to declare that it is doing
   something that can be expensive, and so is worthy of tracing
   representation with a new Span.  `Span.New()` would be a
   function that returned a new sub–span of the original Span.

Anyway I think that's the nutshell of it. Thoughts/questions/concerns?


Re: [go-nuts] Could we trade all the `ctx context.Context` arguments for one pointer in `g`?

2024-02-16 Thread 'Axel Wagner' via golang-nuts
FWIW the common name for this is "dynamic scope":
https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynamic_scope

The general reason this has not been accepted for Go, is that passing a
Context explicitly removes ambiguities what is meant, in the presence of
closures and goroutines.
If you pass a closure to a different execution context (e.g. via a
channel), it has two bindings for any dynamically scoped variable: One in
the source stack and one in the destination stack. Neither of these seems
more clearly correct than the other. Note, for example, that a callback
could be called from a different goroutine altogether, yet close over the
lexical scope of the function it's defined in.
Goroutines also open some questions on how to efficiently implement this
without races. To be fair, Context has the same issue, but by being a
library type, it's used more sparingly, so the performance question is less
critical.

Ultimately, I don't think a lot has changed about this question over the
years.

On Fri, Feb 16, 2024 at 10:43 PM Sam Vilain  wrote:

> Hi all,
>
> Many moons ago I wrote a proposal
>  to
> make *execution context* a fundamental concept in Go, effectively moving `
> context.Context` to being part of the language, not just an extension.
>
> The main reason to do this is that then it would not be up to the source
> maintainer to have to do the refactoring it takes to retrofit `ctx
> context.Context` arguments passed to functions as the first position, as
> has become the common boilerplate.  In some places, this is impossible: for
> instance, the io.Reader and related interfaces forbid a `context.Context`
> argument, so a reader cannot know where it is being read from.
>
> Why does that matter, you might ask?  The main reason is for
> observability: tracing, logging, debugging, etc.  Of course, context should
> in general not be used to alter behavior, but for observability, it seems
> like it would be fair game for the append–only map that `Context`
> provides, to be available even when working with less than stellar code.
>
> I'm wondering how people would feel about this now?
>
> A summary of my original proposal would be to add a "soft" keyword ("
> context") which is only meaningful when used before "var", but would not
> be prohibited from being a variable name.  I did some experimentation with
> the go parser and found I could get code with 'context' added to is passing
> the parsing tests, so I'm pretty sure this would work without slowing
> things down.  That's the syntax I'll use in this message, but of course
> this is subject to feedback and taste.
>
> Some basic principles stated as text for discussion; there are code
> examples in the original proposal from August 2017.
>
>- Semantically, creating a new scope creates a new execution context.
>Hopefully that is a tautology.
>- Context Variables can be declared in any execution context, using 
> `context
>var` instead of plain `var`, and assuming the `context var` is in
>scope of the observer, to all execution scopes created from that execution
>context, including goroutines.
>- The reverse is not true: the only way you can see changes to a
>variable declared in a high level context, is if the variable has a
>pointer, and the sub–level context changes it (i.e., there's no "magic
>const effect" of declaring a variable with context var.)
>- Functions that don't declare context variables use the same context
>as their caller for retrieving context variables.
>   - Declaring it without assigning it in a function allows you to
>   read it, without changing the context.  Like other variables declared
>   without an assignment, reading it from a context with no parent context
>   that has assigned it would reveal the zero value.
>   - You can refer to the old value in the rvalue of the declaration,
>   or at any point from when you declare it to when you assign it within a
>   function.  However, having an assignment in the scope should be thought 
> of
>   creating a new context immediately with an implicit assignment at the
>   declaration.  I think this behavior keeps the semantics as unambiguous 
> as
>   possible, and avoids having to do funny stuff when assigning the 
> variable
>   late in a function.
>   - Scope would work differently.  While the *state* of the value
>follows the execution context, the visibility of the variable would be
>defined by (a) the package the variable is declared in, and (b) the Case of
>the variable.
>   - `context var localInfo` can only be read and written in the
>   package it is declared in.
>   - While reading the rest of this, be careful not to think of the
>   Monty Python Spam song, as this is about Spans, which are not the same.
>   - `context var OpenSpan Span` declares an exported context
>   variab

Re: [go-nuts] Could we trade all the `ctx context.Context` arguments for one pointer in `g`?

2024-02-16 Thread Sam Vilain

Hey Axel, thanks for the response.

   /The general reason this has not been accepted for Go, is that
   passing a Context explicitly removes ambiguities what is meant, in
   the presence of closures and goroutines./
   /If you pass a closure to a different execution context (e.g. via a
   channel), it has two bindings for any dynamically scoped variable:
   One in the source stack and one in the destination stack. Neither of
   these seems more clearly correct than the other. Note, for example,
   that a callback could be called from a different goroutine
   altogether, yet close over the lexical scope of the function it's
   defined in./

It's an interesting question, however we don't need to use goroutines 
and channels to evoke this issue.  Closures are enough.  That is, if you 
make a closure in one function, save it somewhere, and then invoke it 
from a second location, then the closure has two potential scopes that 
could apply.


I would argue that the matter can be simply decided by choosing the 
/calling/ stack, not the destination stack.  Choosing the destination 
stack would mean that the closure no longer really closes over its 
calling context.  It is also possible, where semantics require, to pass 
in specific context variables by value to the closure, and that closure 
can set them in its immediate (and any potential lower) scopes as needed.


If you want the opposite; context carries from the caller of the func, 
instead return a bound method call.  The bound method call can have an 
identical type to a closure, and logically it is the same thing, where 
the struct is the "closure" of state, but it does not restore the 
context register when invoked.  This seems like a clear way to choose 
you want this func to use the /destination/ stack.


   /Goroutines also open some questions on how to efficiently implement
   this without races. To be fair, Context has the same issue, but by
   being a library type, it's used more sparingly, so the performance
   question is less critical./

I don't believe the data structure in Context presents any race 
conditions, and I also don't believe it's necessary for it to remain a 
deep linked list to retain that quality.


For instance, Context could create (static) map[any]any data structures 
for the subsequent contexts it spawns, eg it might decide to do this if 
the number of new contexts that have been created from it exceeds the 
"depth" to the next context with a "flattened" map by some threshold.  
So if it starts to get deep for a context that is creating a bunch of 
new contexts, it creates a flattened map and then switches an internal 
flag.  This can be race–free.  Would an implementation of this help move 
the needle on this, in your view?


Cheers & Happy Friday,
Sam.

--
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/ca15b6de-1e48-4861-ae2c-c9851479f083%40vilain.net.


[go-nuts] Re: Trying to understand aversion to main package

2024-02-16 Thread Rick
Another motivation I have heard used is that an os.Exit() from main 
by-passes defer(). So if you need to use defer from a "main-like" context 
move it to a function called from main(), do your defer(s) in it and then 
do the os.Exit() from main()..

On Friday 16 February 2024 at 01:23:57 UTC-8 Marcello H wrote:

> My main acts just like a mini bootstrap to do as less as possible and hand 
> the real action over to start.Run()
> But is is still testable.
>
> ```
>
> var mainRunner = runner
>
> /* -- Methods/Functions -- */
>
> // runner starts the application and can be overwritten in a test for 
> mocking.
> func runner() error {
> return start.Run() //nolint:wrapcheck // not needed here
> }
>
> /*
> main is the bootstrap of the application.
> */
> func main() {
> err := mainRunner()
> if err != nil {
> fmt.Println("Error:\n", libErrors.GetError(err))
> }
> }
> ```
> In an internal test, the mainRunner is mocked and can emulate an error if 
> needed.
> func Test_Main_Error(t *testing.T) {
> mainRunner = func() error {
> return errors.New("test error")
> }
>
> defer func() {
> mainRunner = runner
> }()
>
> captured := libCapture.Direct(func() {
> main()
> })
>
> assert.Contains(t, captured, "test error")
> }
>
> Op donderdag 15 februari 2024 om 10:05:11 UTC+1 schreef Brian Candler:
>
>> On Thursday 15 February 2024 at 00:08:44 UTC Jerry Londergaard wrote:
>>
>> If code is outside of the main function but still in the main package, it 
>> seems its testable like other functions?
>>
>>
>> Yes indeed.
>>  
>>
>> I suspect though if one is putting tests in package main_test, then I 
>> guess you can't import the main package to test it :(
>>
>>
>> Works fine as far as I can see:
>> https://go.dev/play/p/7UtYP2j8hg6
>>
>> (Tests don't run in the playground, unless you explicitly invoke a 
>> runner, but you can run this locally to demonstrate)
>>
>

-- 
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/ee02c678-faa6-473c-bc81-5899ecf3b159n%40googlegroups.com.


Re: [go-nuts] Re: Range over int

2024-02-16 Thread Amnon
Indeed. The thread started 12 years ago. At the time I thought the idea of 
ranging over an int was just dumb, and un-go-like.
But now it is out, I think it is great, and have run 
perl -pi -e 's/for (\w+) := 0; \1 < ([\w()]+); \1\+\+/for \1 := range 
\2/' $(git grep -l for) over my entire codebase to use it everywhere.

On Friday 16 February 2024 at 01:38:55 UTC Jorge Massih wrote:

> Hey folks! Now in in Go v1.22 (released 02-06-2024) 
>  it's possible to iterate over a range 
> of integers by doing the approach mentioned at the beginning of this 
> conversation.
>
> - JM
> El miércoles, 7 de enero de 2015 a la(s) 9:42:07 p.m. UTC-4, Sean Russell 
> escribió:
>
>> On Wednesday, January 7, 2015 11:51:03 AM UTC-5, tomwilde wrote:
>>>
>>> ... 
>>>
>> Having introduced this convenience range-syntax where you can specify the 
>>> upper bound; wouldn't it by extension make sense to also allow the 
>>> programmer to specify a lower bound à la "x := range a, b".
>>>
>>> And from there people will want list comprehensions, texas ranges, etc, 
>>> etc...
>>>
>>> It's a slippery slope.
>>>
>>
>> There are already people who want list comprehension; you don't need 
>> range syntax changes as a gateway feature for that.
>>
>> --- SER 
>>
>

-- 
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/197f8c57-c78e-48c8-b08a-761ab570189dn%40googlegroups.com.


Re: [go-nuts] Could we trade all the `ctx context.Context` arguments for one pointer in `g`?

2024-02-16 Thread 'Axel Wagner' via golang-nuts
On Sat, Feb 17, 2024 at 2:09 AM Sam Vilain  wrote:

> I would argue that the matter can be simply decided by choosing the
> *calling* stack, not the destination stack.
>

I agree that this is *one choice*. But the point is, that *sometimes* you'd
want one and *sometimes* the other. And no matter which choice you make for
the language - it means that if the programmers wanted the other, they'd
have to jump through annoying hoops and get confusing and hard to debug
problems. So if you want to justify either choice, you have to make an
argument that it is so overwhelmingly more common what people would want,
that the cost of running into these problems is small enough to be
justified by the benefit.

I think that's a hard case to make.

-- 
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/CAEkBMfHk%2BHuQ4Wsji3kZ7sWCUv1cSX3WLpM53Wg1Xtg%2B8e-uFQ%40mail.gmail.com.


Re: [go-nuts] Re: Range over int

2024-02-16 Thread Patrick Smith
On Fri, Feb 16, 2024 at 10:27 PM Amnon  wrote:

> But now it is out, I think it is great, and have run
> perl -pi -e 's/for (\w+) := 0; \1 < ([\w()]+); \1\+\+/for \1 := range
> \2/' $(git grep -l for) over my entire codebase to use it everywhere.
>

You know your own codebase, and maybe this was safe for you to do. But in
general, blindly applying such a blanket change has the potential to cause
bugs, as these two are not always equivalent:

for i := range k
for i := 0; i < k; i++

In particular, if k is changed inside the loop they may be very different.
https://go.dev/play/p/kAHcmu7377I

(Yes, many people, myself included, would consider changing k inside such a
loop to be bad coding style. But "bad style" doesn't mean it's not going to
be done.)

-- 
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/CAADvV_trGNxeLUma722wk-JOGnz42fJqM8%3DVZ36TKpr5s-%3DmOQ%40mail.gmail.com.


Re: [go-nuts] Re: Range over int

2024-02-16 Thread Kurtis Rader
It's not just changing `k` inside the loop body that makes the
transformation invalid -- your observation also applies to modifying `i`
inside the loop body. Modifying either variable inside the loop body is
extremely rare in my experience and doing so warrants a "dragons be here"
comment. Still, your point is valid and anyone applying such a
transformation should carefully evaluate the body of each loop to see if
either variable might be modified by the loop body. Obviously it would be
nice if a tool automated that analysis and transformation but I'm not going
to hold my breath waiting for someone to implement that tool.

On Fri, Feb 16, 2024 at 11:06 PM Patrick Smith  wrote:

> On Fri, Feb 16, 2024 at 10:27 PM Amnon  wrote:
>
>> But now it is out, I think it is great, and have run
>> perl -pi -e 's/for (\w+) := 0; \1 < ([\w()]+); \1\+\+/for \1 :=
>> range \2/' $(git grep -l for) over my entire codebase to use it
>> everywhere.
>>
>
> You know your own codebase, and maybe this was safe for you to do. But in
> general, blindly applying such a blanket change has the potential to cause
> bugs, as these two are not always equivalent:
>
> for i := range k
> for i := 0; i < k; i++
>
> In particular, if k is changed inside the loop they may be very different.
> https://go.dev/play/p/kAHcmu7377I
>
> (Yes, many people, myself included, would consider changing k inside such
> a loop to be bad coding style. But "bad style" doesn't mean it's not going
> to be done.)
>
> --
> 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/CAADvV_trGNxeLUma722wk-JOGnz42fJqM8%3DVZ36TKpr5s-%3DmOQ%40mail.gmail.com
> 
> .
>


-- 
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

-- 
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/CABx2%3DD9Hyjj_N9KjY6XfFH0ZUt55f27VCcZQSj_DyX36gzrX1g%40mail.gmail.com.