Re: [go-nuts] CGO - convert a c.char array to string

2018-08-05 Thread nicolas_boiteux via golang-nuts
thanks you, the A3 community finaly help me to solve the last problem




*for index := C.int(0); index < argc; index++ {out = 
append(out, C.GoString(*argv))argv = 
(**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(argv)) + offset))}*

I dont really understand why but it seems there was a problem with my 
casting method with unsafe

*(*int)(unsafe.Pointer(limit)

Le dimanche 5 août 2018 15:02:47 UTC+2, Jan Mercl a écrit :
>
> On Sun, Aug 5, 2018 at 2:50 PM nicolas_boiteux via golang-nuts <
> golan...@googlegroups.com > wrote:
>
> > not sure to understand cause the iteration in your example is done on os 
> interface from golang not from c char array :(
>
> Not sure what you mean by 'os interface'. Here's the part that iterates 
> **C.char, except pointers are transformed to uintptrs. Other that that it's 
> what you're, I think, after
>
> // Xmain is defined at main.c:3:5
> func Xmain(tls crt.TLS, _argc int32, _argv uintptr /* **int8 */) (r int32) 
> {
> var _p uintptr // **int8
>
> _p = _argv
> _1:
> if (*(*uintptr)(unsafe.Pointer(_p))) == 0 {
> goto _3
> }
>
> crt.Xprintf(tls, ts+0 /* "%s\n" */, *(*uintptr)(unsafe.Pointer(_p)))
> _p += 8
> goto _1
>
> _3:
> return r
> }
>
> Manually converting (untested again):
>
> func foo(argv **C.char) []string {
> var a []string
> for p := argv; *p != nil; *(*uintptr)(unsafe.Pointer(p)) += 
> unsafe.Sizeof(*p) {
> a = append(a, GoString(*p))
> }
> rerurn a
> }
>
>
> -- 
>
> -j
>

-- 
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] Re: looking for a flexible file path resolver

2018-08-05 Thread Behrad Khodayar
Have you tried filepath  package 
from path . It handles such things based on 
OS & etc. Hope it helps

On Monday, 6 August 2018 06:49:15 UTC+4:30, DrGo wrote:
>
> In many applications, I need to resolve an arbitrary file name that a user 
> provided to a valid file-system path that can be used to open, create or 
> append to a file. I think I now have written 4 funcs to achieve one or 
> another of these objectives, but none that is flexible enough and robust 
> enough to cope with most common scenarios. Do you know of a well-tested 
> func that does the following:
> - can resolve a filename to a path whether the provided filename is 
> absolute, relative to a provided default directory or the working dir 
> (e.g., ../../fname, just fname etc) if the default directory is an empty 
> string.
> - return an error if the filename cannot be resolved eg due to malformed 
> path
> - check if the file must not exist, must exist, must be a file (or 
> directory) etc as specified.
>
> I am thinking that some of the more complex applications out there (eg 
> docker, go build tools) must have implemented a similar function, and was 
> hoping someone could point me in the right direction.
>
> 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] How to update packages without duplicating distro packages

2018-08-05 Thread Kevin Locke
Hello,

Is there a way to update packages installed using `go get` without
duplicating packages that are distributed with Go or by my Linux
distribution?

Background:  I'm not a Go developer (yet).  I am using some programs
written in Go, which I installed using `go get`, and would like to
keep those programs up to date.  Running `go get -u all` or
`cd ~/go && go get -u ./...` both result in many packages being
downloaded and rebuilt unnecessarily (and more with each invocation),
which slows updates significantly and wastes a lot of disk space.
Is there a command which I can run that only updates the packages I
have installed and their dependencies without updating packages
installed system-wide?

As a specific example (using Debian golang-go 2:1.10~5):

$ rm -rf ~/go
$ go get -u mvdan.cc/sh/cmd/shfmt
$ cd ~/go
$ du -hs .
7.8M.
$ go list ./... | wc -l
6
$ go get -u ./...
$ du -hs .
46M .
$ go list ./... | wc -l
98
$ go get -u ./...
$ du -hs .
111M.
$ go list ./... | wc -l
160
$ du -hs .
181M.
$ go list ./... | wc -l
235

(Since each `go get` takes longer to complete, I have not waited until
a stable state is reached.)

Any suggestions or pointers to documentation that I may have
overlooked would be much appreciated.

Thanks,
Kevin

-- 
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] "go" binutils test failure when building from source using "bootstrap go"

2018-08-05 Thread J. Hart

On 07/20/2018 02:55 PM, Ian Lance Taylor wrote:
Thanks. But when binutils.test runs /usr/bin/nm -n, it doesn't see 
anything? I'm actually not quite clear on what the problem is. Ian 


There is a failure when running all.bash as follows:

ok  cmd/trace   0.028s
--- FAIL: TestObjFile (0.17s)
binutils_test.go:237: SourceLine for main: expect [{main 
/tmp/hello.c 3}]; got [{main  0}]

FAIL
FAILcmd/vendor/github.com/google/pprof/internal/binutils 0.371s


A similar failure occurs when running the binutils test alone as follows:

go tool dist test -run cmd/vendor/github.com/google/pprof/internal/binutils


It appears that the process running binutils.test forks a process which 
calls /usr/bin/nm.  This latter process appears to complete correctly 
(zero status), and the output of nm can be seen in the strace log.  The 
process running "binutils.test" appears to fail shortly after the 
"/usr/binutils.test" returns.


--
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] Re: Better way to get the exit status of an os/exec command?

2018-08-05 Thread bucarr
Don't know if this is easier, agree no present way is easy enough, but this 
worked for one project I was working on:

cmd := exec.Command("zfs", "get", "all")
_ = cmd.Run() // shamelessly discard any error
exitcode := cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
if exitcode != 0 {
   whatever...
}

Bucky

-- 
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] "go" binutils test failure when building from source using "bootstrap go"

2018-08-05 Thread Ian Lance Taylor
On Fri, Jul 20, 2018 at 12:56 PM, J. Hart  wrote:
> On 07/20/2018 02:55 PM, Ian Lance Taylor wrote:
>>
>> Thanks. But when binutils.test runs /usr/bin/nm -n, it doesn't see
>> anything? I'm actually not quite clear on what the problem is. Ian
>
>
> There is a failure when running all.bash as follows:
>
> ok  cmd/trace   0.028s
> --- FAIL: TestObjFile (0.17s)
> binutils_test.go:237: SourceLine for main: expect [{main
> /tmp/hello.c 3}]; got [{main  0}]
> FAIL
> FAILcmd/vendor/github.com/google/pprof/internal/binutils 0.371s
>
>
> A similar failure occurs when running the binutils test alone as follows:
>
> go tool dist test -run cmd/vendor/github.com/google/pprof/internal/binutils
>
>
> It appears that the process running binutils.test forks a process which
> calls /usr/bin/nm.  This latter process appears to complete correctly (zero
> status), and the output of nm can be seen in the strace log.  The process
> running "binutils.test" appears to fail shortly after the
> "/usr/binutils.test" returns.

Open an issue, I guess, at https://golang.org/issue.  Doesn't seem
like anybody else is seeing this.

(Note that your build is completely usable at this point, this test
failure is not important.)

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] Re: Better way to get the exit status of an os/exec command?

2018-08-05 Thread Manlio Perillo
Il giorno venerdì 20 luglio 2018 22:02:15 UTC+2, buc...@gmail.com ha 
scritto:
>
> Don't know if this is easier, agree no present way is easy enough, but 
> this worked for one project I was working on:
>
> cmd := exec.Command("zfs", "get", "all")
> _ = cmd.Run() // shamelessly discard any error
> exitcode := cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
> if exitcode != 0 {
>whatever...
> }
>
>
This does not work on plan9, where you need to do:
exitcode := cmd.ProcessState.Sys().(syscall.Waitmsg).ExitStatus()


Also, may not work on future supported operating systems.


Manlio 

-- 
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] "go" binutils test failure when building from source using "bootstrap go"

2018-08-05 Thread J. Hart

On 07/20/2018 04:01 PM, Ian Lance Taylor wrote:

Open an issue, I guess, at https://golang.org/issue.  Doesn't seem
like anybody else is seeing this.

(Note that your build is completely usable at this point, this test
failure is not important.)

Ian



Thank you for your time and attention.   I do tend to think all test 
failures are important.  I'll consider filing an issue.


With Thanks,

J. Hart

--
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] looking for a flexible file path resolver

2018-08-05 Thread DrGo
In many applications, I need to resolve an arbitrary file name that a user 
provided to a valid file-system path that can be used to open, create or 
append to a file. I think I now have written 4 funcs to achieve one or 
another of these objectives, but none that is flexible enough and robust 
enough to cope with most common scenarios. Do you know of a well-tested 
func that does the following:
- can resolve a filename to a path whether the provided filename is 
absolute, relative to a provided default directory or the working dir 
(e.g., ../../fname, just fname etc) if the default directory is an empty 
string.
- return an error if the filename cannot be resolved eg due to malformed 
path
- check if the file must not exist, must exist, must be a file (or 
directory) etc as specified.

I am thinking that some of the more complex applications out there (eg 
docker, go build tools) must have implemented a similar function, and was 
hoping someone could point me in the right direction.

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] Re: Possible missing atomic load(s)/store(s) in runtime/chan.go?

2018-08-05 Thread Ian Lance Taylor
On Sun, Aug 5, 2018 at 12:12 PM, Marvin Stenger
 wrote:
>
> We talk about the implementation of chansend/recv, where fast paths are not
> protected by a locked mutex (slow paths of course are). And those fast paths
> use atomic.Loads intentially sparse, which could look inconsistent if not
> familiar with the design/mechanics behind it.
> And my point was, that a slow path protected with a lock surely can execute
> concurrently with a fast path not protected by that lock. So for the fast
> path implementation one has to know what one is doing and if reordering
> issues are a concern or not or if there could even be real data races on the
> shared resource if accessed non-atomically.

Yes, it is definitely possible to get things wrong when combining a
fast path not protected with a mutex with a slow path that is
protected by a mutex.  But it is also possible to get things right.
Do you see a specific problem in the code?

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] Re: Possible missing atomic load(s)/store(s) in runtime/chan.go?

2018-08-05 Thread Jan Mercl
On Sun, Aug 5, 2018 at 9:01 PM Marvin Stenger 
wrote:

> What: Code path protected by a mutex
> Does what: does not execute concurrently

> Surely it can execute concurrently, and even in parallel if your machine
has more than one core.

Then we are using the same word for different meanings, hence the
confusion. By a mutex I mean this:
https://en.wikipedia.org/wiki/Mutual_exclusion and in this meaning there's
no concurrent execution of the code path protected by a mutex.

-- 

-j

-- 
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] Re: Possible missing atomic load(s)/store(s) in runtime/chan.go?

2018-08-05 Thread Jan Mercl
On Sun, Aug 5, 2018 at 8:25 PM Marvin Stenger 
wrote:

> Well it does.

Does what? Even, what does what?

> For this this case of chan.go there are multiple reasons working
together, why it is ok to sometimes use a lock, othertimes only atomic
access or even plain access:

Maybe I misunderstand something. Are we both talking about a code path
protected by a locked mutex and thus executing in a single goroutine with
no other goroutine concurrently accessing the data protected by the mutex,
ie.  in a way such that no two goroutines read _and_ write the same data
within the protected path? (Concurrent reads, but only reads are ok.)

-- 

-j

-- 
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] WebSocket implementation in Go

2018-08-05 Thread Sergey Kamardin
Hi Gophers,

I have released a stable v1.0 version of https://github.com/gobwas/ws.

It implements RFC6455 and supports streaming, manual memory management and
other things for writing memory efficient WebSocket applications.

By the way it deals with highload in production servers for almost two
years (interacting with about 3 millions connections and so on).
Here is an article related to it:
https://medium.freecodecamp.org/million-websockets-and-go-cc58418460bb.

--
Sergey.

-- 
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] Go not exists as Technology in Google Developers Experts

2018-08-05 Thread Sameer Ajmani
Very good question! I'll follow up on this, thank you.
On Sun, Aug 5, 2018 at 7:56 AM Davor Kapša  wrote:

> Why Go not listed ?
>
> https://developers.google.com/experts/all/technology
>
> --
> 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.
>

-- 
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] Re: ParseFiles equivalent for strings?

2018-08-05 Thread adam.azarchs via golang-nuts
You can, if you wish, get the best of both worlds by using go generate and 
a tool like https://github.com/shurcooL/vfsgen to automatically generate go 
source from those files.

On Sunday, August 5, 2018 at 7:33:41 AM UTC-7, buc...@gmail.com wrote:
>
> After changing from embedding my .html/css code in the body of my .go 
> program, to making a separate, stand-alone .html/css file and including a  
> template.Must(template.ParseFiles("filename.html"))' line in the .go source 
> file, I can see that the go creators are a lot smarter than I am.
>
> MUCH easier to work with the separate files than having them combined.
>
> Thanks to all who waded in on this pretty silly pondering of mine.
>
>

-- 
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] Re: Possible missing atomic load(s)/store(s) in runtime/chan.go?

2018-08-05 Thread Jan Mercl
On Sun, Aug 5, 2018 at 7:28 PM  wrote:

> It is also my understanding that writes within a locked region that are
read in some fast path without holding the lock need to be atomic writes.
And the write to c.closed in closechan is NOT atomic.

Code path protected by a mutex does nor execute concurrently. No need for
atomic R/W ops.

-- 

-j

-- 
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] Re: Possible missing atomic load(s)/store(s) in runtime/chan.go?

2018-08-05 Thread grapolu
I have read those comments. However, I still can't understand why it is 
safe for chansend to NOT use atomic.Load for c.closed when chanrecv does 
use it. 

It is also my understanding that writes within a locked region that are 
read in some fast path without holding the lock need to be atomic writes. 
And the write to c.closed in closechan is NOT atomic.

-- 
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] Re: avoiding os thread creation due to logging

2018-08-05 Thread grapolu
You can use a semaphore-like pattern described 
in https://tip.golang.org/ref/mem to limit the number of goroutines trying 
to concurrently write to the log file. This remove the need for the 
buffering scheme.

On Sunday, August 5, 2018 at 9:32:06 AM UTC-7, Anuj Agrawal wrote:
>
> I have an application with more than 50k goroutines. I pass a context to 
> each of these goroutines which contains a logger and that logger writes to 
> a file. At some point, the number of goroutines trying to write a log 
> peaked and my application crashed with - runtime: program exceeds 
> 1-thread limitfatal error: thread exhaustion.
>
> To provide a quick fix, I added a writer in between the logger and the 
> file writer which would buffer all logs in a channel and a separate 
> goroutine can then read from the channel and write to the file, thus, 
> avoiding having to create so many OS threads. Something like:
>
> type writer struct {
> wg sync.WaitGroup
> buffer chan []byte
> outio.WriteCloser
> pool   sync.Pool
> }
>
> func (w *writer) Write(p []byte) (int, error) {
> tmp := w.pool.Get().([]byte)
> tmp = append(tmp[:0], p...)
> w.buffer <- tmp
> return len(tmp), nil
> }
>
> go func() {
> for p := range w.buffer {
> if _, err := w.out.Write(p); err != nil {
> log.Printf("error writing to log file: %s\n%s\n", err.Error(), string(p))
> }
> w.pool.Put(p)
> }
> w.wg.Done()
> }()
>
>
>
> I want to have suggestions if it can be fixed in a better way.
>

-- 
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] Re: How to reuse go fix tool code

2018-08-05 Thread Anuj Agrawal
On Sun, Mar 18, 2018 at 10:17 PM,  wrote:

> Hi Anuj,
>
> Two quick comments.
>
> 1. FYI, in case you didn't see this in the recent vgo dependency
> management  discussion, go fix might start to be used much more broadly in
> the not-too-distant future across the go community as a way to help
> automate in some cases the ability to update client code as a way to help
> manage API changes, somewhat similar to how go fix was used by the core go
> team before go 1.0. See the snippet pasted below from one of rsc's recent
> blog posts, or visit that link for a longer discussion. Not yet
> implemented, but could be very nice if it happens.
>
> 2. I'm mildly curious what type of changes you are trying to do, including
> what aspect of your intended changes makes it such that the simpler 'gofmt
> -r' automated refactoring or the more flexible 'eg' example-based
> refactoring tool (from the go team) aren't applicable.  The 'eg' help is
> mildly annoying to track down via godoc, so forgive the volume of text but
> I pasted in the main help text below from 'eg' at the bottom of this post.
> 'eg' is focused on expression-level changes, so perhaps that is one reason
> it might not be applicable for you, but as I said I'm a bit curious about
> the specifics of your case...
>
>
Thanks, I will try it out and will post here if I find a case where it does
not work. I had read the gofix blog
 and thought it should solve my
problem.


> 
> from https://research.swtch.com/vgo-import
> 
> Before Go 1, we relied heavily on go fix, which users ran after updating
> to a new Go release and finding their programs no longer compiled.
>
> ...
>
> The ability to name and work with multiple incompatible versions of a
> package in a single program suggests a possible solution: if a v1 API
> function can be implemented as a wrapper around the v2 API, the wrapper
> implementation can double as the fix specification. For example, suppose v1
> of an API has functions EnableFoo and DisableFoo and v2 replaces the pair
> with a single SetFoo(enabled bool). After v2 is released, v1 can be
> implemented as a wrapper around v2:
>
> package p // v1
>
> import v2 "p/v2"
>
> func EnableFoo() {
> //go:fix
> v2.SetFoo(true)
> }
>
> func DisableFoo() {
> //go:fix
> v2.SetFoo(false)
> }
>
> The special //go:fix comments would indicate to go fix that the wrapper
> body that follows should be inlined into the call site. Then running go fix
> would rewrite calls to v1 EnableFoo to v2 SetFoo(true). The rewrite is
> easily specified and type-checked, since it is plain Go code.
> 
>
>
> 
> from golang/tools eg help via https://github.com/golang/
> tools/blob/release-branch.go1.10/refactor/eg/eg.go#L20
> 
> This tool implements example-based refactoring of expressions.
>
> The transformation is specified as a Go file defining two functions,
> 'before' and 'after', of identical types.  Each function body consists
> of a single statement: either a return statement with a single
> (possibly multi-valued) expression, or an expression statement.  The
> 'before' expression specifies a pattern and the 'after' expression its
> replacement.
>
> package P
>   import ( "errors"; "fmt" )
>   func before(s string) error { return fmt.Errorf("%s", s) }
>   func after(s string)  error { return errors.New(s) }
>
> The expression statement form is useful when the expression has no
> result, for example:
>
>   func before(msg string) { log.Fatalf("%s", msg) }
>   func after(msg string)  { log.Fatal(msg) }
>
> The parameters of both functions are wildcards that may match any
> expression assignable to that type.  If the pattern contains multiple
> occurrences of the same parameter, each must match the same expression
> in the input for the pattern to match.  If the replacement contains
> multiple occurrences of the same parameter, the expression will be
> duplicated, possibly changing the side-effects.
>
> The tool analyses all Go code in the packages specified by the
> arguments, replacing all occurrences of the pattern with the
> substitution.
>
> So, the transform above would change this input:
> err := fmt.Errorf("%s", "error: " + msg)
> to this output:
> err := errors.New("error: " + msg)
>
> Identifiers, including qualified identifiers (p.X) are considered to
> match only if they denote the same object.  This allows correct
> matching even in the presence of dot imports, named imports and
> locally shadowed package names in the input program.
>
> Matching of type syntax is semantic, not syntactic: type syntax in the
> pattern matches type syntax in the input if the types are identical.
> Thus, func(x int) matches func(y int).
>
> This tool was inspired by 

[go-nuts] avoiding os thread creation due to logging

2018-08-05 Thread Anuj Agrawal
I have an application with more than 50k goroutines. I pass a context to
each of these goroutines which contains a logger and that logger writes to
a file. At some point, the number of goroutines trying to write a log
peaked and my application crashed with - runtime: program exceeds
1-thread limitfatal error: thread exhaustion.

To provide a quick fix, I added a writer in between the logger and the file
writer which would buffer all logs in a channel and a separate goroutine
can then read from the channel and write to the file, thus, avoiding having
to create so many OS threads. Something like:

type writer struct {
wg sync.WaitGroup
buffer chan []byte
outio.WriteCloser
pool   sync.Pool
}

func (w *writer) Write(p []byte) (int, error) {
tmp := w.pool.Get().([]byte)
tmp = append(tmp[:0], p...)
w.buffer <- tmp
return len(tmp), nil
}

go func() {
for p := range w.buffer {
if _, err := w.out.Write(p); err != nil {
log.Printf("error writing to log file: %s\n%s\n", err.Error(), string(p))
}
w.pool.Put(p)
}
w.wg.Done()
}()



I want to have suggestions if it can be fixed in a better way.

-- 
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] CGO - convert a c.char array to string

2018-08-05 Thread nicolas_boiteux via golang-nuts
i found another thing.

func RVExtensionArgs(output *C.char, outputsize C.size_t, input *C.char, 
argv **C.char, argc C.int) {
var offset = unsafe.Sizeof(uintptr(0))
var out []string






*limit := *(*int)(unsafe.Pointer())if limit < 1000 {
for index := 0; index < limit; index++ {out = append(out, 
C.GoString(*argv))argv = 
(**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(argv)) + offset))
}}*
temp := fmt.Sprintf("Hello %s %d %s!", C.GoString(input), limit,  out)

// Return a result to Arma
result := C.CString(temp)
defer C.free(unsafe.Pointer(result))
var size = C.strlen(result) + 1
if size > outputsize {
size = outputsize
}
C.memmove(unsafe.Pointer(output), unsafe.Pointer(result), size)
}Saisissez le code ici...
it seems there is also a bug in the main program cause the argc variable, 
the first execution time contains a memory adress instead of int


Le dimanche 5 août 2018 15:47:00 UTC+2, nicolas...@yahoo.fr a écrit :
>
> Miki & Jan thanks
>
> i tested the both methods. Dll compiles normaly, but program crash.
>
> With Miki code the first time, i run the code, i saw that string array 
> contains also other characters that not come from argv.
>
> Le dimanche 5 août 2018 15:02:47 UTC+2, Jan Mercl a écrit :
>>
>> On Sun, Aug 5, 2018 at 2:50 PM nicolas_boiteux via golang-nuts <
>> golan...@googlegroups.com> wrote:
>>
>> > not sure to understand cause the iteration in your example is done on 
>> os interface from golang not from c char array :(
>>
>> Not sure what you mean by 'os interface'. Here's the part that iterates 
>> **C.char, except pointers are transformed to uintptrs. Other that that it's 
>> what you're, I think, after
>>
>> // Xmain is defined at main.c:3:5
>> func Xmain(tls crt.TLS, _argc int32, _argv uintptr /* **int8 */) (r 
>> int32) {
>> var _p uintptr // **int8
>>
>> _p = _argv
>> _1:
>> if (*(*uintptr)(unsafe.Pointer(_p))) == 0 {
>> goto _3
>> }
>>
>> crt.Xprintf(tls, ts+0 /* "%s\n" */, *(*uintptr)(unsafe.Pointer(_p)))
>> _p += 8
>> goto _1
>>
>> _3:
>> return r
>> }
>>
>> Manually converting (untested again):
>>
>> func foo(argv **C.char) []string {
>> var a []string
>> for p := argv; *p != nil; *(*uintptr)(unsafe.Pointer(p)) += 
>> unsafe.Sizeof(*p) {
>> a = append(a, GoString(*p))
>> }
>> rerurn a
>> }
>>
>>
>> -- 
>>
>> -j
>>
>

-- 
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] Re: ParseFiles equivalent for strings?

2018-08-05 Thread bucarr
After changing from embedding my .html/css code in the body of my .go 
program, to making a separate, stand-alone .html/css file and including a  
template.Must(template.ParseFiles("filename.html"))' line in the .go source 
file, I can see that the go creators are a lot smarter than I am.

MUCH easier to work with the separate files than having them combined.

Thanks to all who waded in on this pretty silly pondering of mine.

-- 
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] CGO - convert a c.char array to string

2018-08-05 Thread nicolas_boiteux via golang-nuts
Miki & Jan thanks

i tested the both methods. Dll compiles normaly, but program crash.

With Miki code the first time, i run the code, i saw that string array 
contains also other characters that not come from argv.

Le dimanche 5 août 2018 15:02:47 UTC+2, Jan Mercl a écrit :
>
> On Sun, Aug 5, 2018 at 2:50 PM nicolas_boiteux via golang-nuts <
> golan...@googlegroups.com > wrote:
>
> > not sure to understand cause the iteration in your example is done on os 
> interface from golang not from c char array :(
>
> Not sure what you mean by 'os interface'. Here's the part that iterates 
> **C.char, except pointers are transformed to uintptrs. Other that that it's 
> what you're, I think, after
>
> // Xmain is defined at main.c:3:5
> func Xmain(tls crt.TLS, _argc int32, _argv uintptr /* **int8 */) (r int32) 
> {
> var _p uintptr // **int8
>
> _p = _argv
> _1:
> if (*(*uintptr)(unsafe.Pointer(_p))) == 0 {
> goto _3
> }
>
> crt.Xprintf(tls, ts+0 /* "%s\n" */, *(*uintptr)(unsafe.Pointer(_p)))
> _p += 8
> goto _1
>
> _3:
> return r
> }
>
> Manually converting (untested again):
>
> func foo(argv **C.char) []string {
> var a []string
> for p := argv; *p != nil; *(*uintptr)(unsafe.Pointer(p)) += 
> unsafe.Sizeof(*p) {
> a = append(a, GoString(*p))
> }
> rerurn a
> }
>
>
> -- 
>
> -j
>

-- 
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] CGO - convert a c.char array to string

2018-08-05 Thread Jan Mercl
On Sun, Aug 5, 2018 at 2:50 PM nicolas_boiteux via golang-nuts <
golang-nuts@googlegroups.com> wrote:

> not sure to understand cause the iteration in your example is done on os
interface from golang not from c char array :(

Not sure what you mean by 'os interface'. Here's the part that iterates
**C.char, except pointers are transformed to uintptrs. Other that that it's
what you're, I think, after

// Xmain is defined at main.c:3:5
func Xmain(tls crt.TLS, _argc int32, _argv uintptr /* **int8 */) (r int32) {
var _p uintptr // **int8

_p = _argv
_1:
if (*(*uintptr)(unsafe.Pointer(_p))) == 0 {
goto _3
}

crt.Xprintf(tls, ts+0 /* "%s\n" */, *(*uintptr)(unsafe.Pointer(_p)))
_p += 8
goto _1

_3:
return r
}

Manually converting (untested again):

func foo(argv **C.char) []string {
var a []string
for p := argv; *p != nil; *(*uintptr)(unsafe.Pointer(p)) +=
unsafe.Sizeof(*p) {
a = append(a, GoString(*p))
}
rerurn a
}


-- 

-j

-- 
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] Re: CGO - convert a c.char array to string

2018-08-05 Thread Miki Tebeka
Hi,
 

> i have a little problem to convert a C char array to a string array in 
> golang
>
Maybe something like

var offset = unsafe.Sizeof(uintptr(0))

func argv2go(argv **C.char) []string {
var out []string
for *argv != nil {
out = append(out, C.GoString(*argv))
argv = (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(argv)) + 
offset))
}

return out
}


 

-- 
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] CGO - convert a c.char array to string

2018-08-05 Thread nicolas_boiteux via golang-nuts
not sure to understand cause the iteration in your example is done on os 
interface from golang not from c char array :(

Le dimanche 5 août 2018 12:48:20 UTC+2, Jan Mercl a écrit :
>
> On Sun, Aug 5, 2018 at 12:29 PM nicolas_boiteux via golang-nuts <
> golan...@googlegroups.com > wrote:
>
> > it returns :
> >
> > .\armago_x64.go:19: cannot convert p (type **_Ctype_char) to type uintptr
>
> Ok, this time bit more tested
>
> jnml@4670:~/tmp> cat main.c
> #include 
>
> int main(int argc, char **argv) {
> char **p;
> for (p = argv; *p != 0; p++) {
> printf("%s\n", *p);
> }
> }
> jnml@4670:~/tmp> ccgo main.c && ./a.out abc def ghi
> ./a.out
> abc
> def
> ghi
> jnml@4670:~/tmp> ccgo -o main.go main.c
> jnml@4670:~/tmp> cat main.go
> // Code generated by 'ccgo -o main.go main.c', DO NOT EDIT.
>
> // +build linux,amd64
>
> package main
>
> import (
> "math"
> "os"
> "unsafe"
>
> "github.com/cznic/crt"
> )
>
> const (
> null = uintptr(0)
> )
>
> var (
> _ = math.Pi
> _ = os.DevNull
> _ = unsafe.Pointer(null)
>
> nz32 float32
> nz64 float64
> )
>
> func init() { nz32 = -nz32 }
> func init() { nz64 = -nz64 }
>
> func alloca(p *[]uintptr, n int) uintptr   { r := crt.MustMalloc(n); *p = 
> append(*p, r); return r }
> func preinc(p *uintptr, n uintptr) uintptr { *p += n; return *p }
>
> func main() {
> psz := unsafe.Sizeof(uintptr(0))
> argv := crt.MustCalloc((len(os.Args) + 1) * int(psz))
> p := argv
> for _, v := range os.Args {
> *(*uintptr)(unsafe.Pointer(p)) = crt.CString(v)
> p += psz
> }
> a := os.Environ()
> env := crt.MustCalloc((len(a) + 1) * int(psz))
> p = env
> for _, v := range a {
> *(*uintptr)(unsafe.Pointer(p)) = crt.CString(v)
> p += psz
> }
> *(*uintptr)(unsafe.Pointer(Xenviron)) = env
> X_start(crt.NewTLS(), int32(len(os.Args)), argv)
> }
>
> // linking main.o
>
> // X__ccgo_va_end *void, escapes: true, builtin.h:36:6
> var X__ccgo_va_end = bss + 0
>
> // X__ccgo_va_start *void, escapes: true, builtin.h:37:6
> var X__ccgo_va_start = bss + 8
>
> // Xmain is defined at main.c:3:5
> func Xmain(tls crt.TLS, _argc int32, _argv uintptr /* **int8 */) (r int32) 
> {
> var _p uintptr // **int8
>
> _p = _argv
> _1:
> if (*(*uintptr)(unsafe.Pointer(_p))) == 0 {
> goto _3
> }
>
> crt.Xprintf(tls, ts+0 /* "%s\n" */, *(*uintptr)(unsafe.Pointer(_p)))
> _p += 8
> goto _1
>
> _3:
> return r
> }
>
> // linking crt0.o
>
> // X__stdfiles [3]uintptr, escapes: true, crt0.c:3:15
> var X__stdfiles = bss + 16
>
> // Xenviron **int8, escapes: true, crt0.c:4:6
> var Xenviron = bss + 40
>
> // Xstdin *void, escapes: true, crt0.c:5:6
> var Xstdin = bss + 48 // pointer to void
>
> func init() { *(*uintptr)(unsafe.Pointer(Xstdin)) = X__stdfiles }
>
> // Xstdout *void, escapes: true, crt0.c:5:31
> var Xstdout = bss + 56 // pointer to void
>
> func init() { *(*uintptr)(unsafe.Pointer(Xstdout)) = X__stdfiles + 8 }
>
> // Xstderr *void, escapes: true, crt0.c:5:57
> var Xstderr = bss + 64 // pointer to void
>
> func init() { *(*uintptr)(unsafe.Pointer(Xstderr)) = X__stdfiles + 16 }
>
> // X_start is defined at crt0.c:7:6
> func X_start(tls crt.TLS, _argc int32, _argv uintptr /* **int8 */) {
> crt.X__register_stdfiles(tls, *(*uintptr)(unsafe.Pointer(Xstdin)), 
> *(*uintptr)(unsafe.Pointer(Xstdout)), *(*uintptr)(unsafe.Pointer(Xstderr)), 
> Xenviron)
> crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv))
> }
>
> func init() { *(*uintptr)(unsafe.Pointer(Xstdin)) = X__stdfiles }
>
> func init() { *(*uintptr)(unsafe.Pointer(Xstdout)) = X__stdfiles + 8 }
>
> func init() { *(*uintptr)(unsafe.Pointer(Xstderr)) = X__stdfiles + 16 }
>
> var (
> bss = crt.BSS([0])
> bssInit [72]byte
> ts  = crt.TS("%s\n\x00")
> )
> jnml@4670:~/tmp> 
>
> I hope you can extract the code for your case from the above mechanically 
> produced Go code. Note that ccgo uses untrptrs instead of normal pointers 
> but that should be an easy adjustment, I hope.
>
> -- 
>
> -j
>

-- 
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] Go not exists as Technology in Google Developers Experts

2018-08-05 Thread Davor Kapša
Why Go not listed ?

https://developers.google.com/experts/all/technology

-- 
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] CGO - convert a c.char array to string

2018-08-05 Thread Jan Mercl
On Sun, Aug 5, 2018 at 12:29 PM nicolas_boiteux via golang-nuts <
golang-nuts@googlegroups.com> wrote:

> it returns :
>
> .\armago_x64.go:19: cannot convert p (type **_Ctype_char) to type uintptr

Ok, this time bit more tested

jnml@4670:~/tmp> cat main.c
#include 

int main(int argc, char **argv) {
char **p;
for (p = argv; *p != 0; p++) {
printf("%s\n", *p);
}
}
jnml@4670:~/tmp> ccgo main.c && ./a.out abc def ghi
./a.out
abc
def
ghi
jnml@4670:~/tmp> ccgo -o main.go main.c
jnml@4670:~/tmp> cat main.go
// Code generated by 'ccgo -o main.go main.c', DO NOT EDIT.

// +build linux,amd64

package main

import (
"math"
"os"
"unsafe"

"github.com/cznic/crt"
)

const (
null = uintptr(0)
)

var (
_ = math.Pi
_ = os.DevNull
_ = unsafe.Pointer(null)

nz32 float32
nz64 float64
)

func init() { nz32 = -nz32 }
func init() { nz64 = -nz64 }

func alloca(p *[]uintptr, n int) uintptr   { r := crt.MustMalloc(n); *p =
append(*p, r); return r }
func preinc(p *uintptr, n uintptr) uintptr { *p += n; return *p }

func main() {
psz := unsafe.Sizeof(uintptr(0))
argv := crt.MustCalloc((len(os.Args) + 1) * int(psz))
p := argv
for _, v := range os.Args {
*(*uintptr)(unsafe.Pointer(p)) = crt.CString(v)
p += psz
}
a := os.Environ()
env := crt.MustCalloc((len(a) + 1) * int(psz))
p = env
for _, v := range a {
*(*uintptr)(unsafe.Pointer(p)) = crt.CString(v)
p += psz
}
*(*uintptr)(unsafe.Pointer(Xenviron)) = env
X_start(crt.NewTLS(), int32(len(os.Args)), argv)
}

// linking main.o

// X__ccgo_va_end *void, escapes: true, builtin.h:36:6
var X__ccgo_va_end = bss + 0

// X__ccgo_va_start *void, escapes: true, builtin.h:37:6
var X__ccgo_va_start = bss + 8

// Xmain is defined at main.c:3:5
func Xmain(tls crt.TLS, _argc int32, _argv uintptr /* **int8 */) (r int32) {
var _p uintptr // **int8

_p = _argv
_1:
if (*(*uintptr)(unsafe.Pointer(_p))) == 0 {
goto _3
}

crt.Xprintf(tls, ts+0 /* "%s\n" */, *(*uintptr)(unsafe.Pointer(_p)))
_p += 8
goto _1

_3:
return r
}

// linking crt0.o

// X__stdfiles [3]uintptr, escapes: true, crt0.c:3:15
var X__stdfiles = bss + 16

// Xenviron **int8, escapes: true, crt0.c:4:6
var Xenviron = bss + 40

// Xstdin *void, escapes: true, crt0.c:5:6
var Xstdin = bss + 48 // pointer to void

func init() { *(*uintptr)(unsafe.Pointer(Xstdin)) = X__stdfiles }

// Xstdout *void, escapes: true, crt0.c:5:31
var Xstdout = bss + 56 // pointer to void

func init() { *(*uintptr)(unsafe.Pointer(Xstdout)) = X__stdfiles + 8 }

// Xstderr *void, escapes: true, crt0.c:5:57
var Xstderr = bss + 64 // pointer to void

func init() { *(*uintptr)(unsafe.Pointer(Xstderr)) = X__stdfiles + 16 }

// X_start is defined at crt0.c:7:6
func X_start(tls crt.TLS, _argc int32, _argv uintptr /* **int8 */) {
crt.X__register_stdfiles(tls, *(*uintptr)(unsafe.Pointer(Xstdin)),
*(*uintptr)(unsafe.Pointer(Xstdout)), *(*uintptr)(unsafe.Pointer(Xstderr)),
Xenviron)
crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv))
}

func init() { *(*uintptr)(unsafe.Pointer(Xstdin)) = X__stdfiles }

func init() { *(*uintptr)(unsafe.Pointer(Xstdout)) = X__stdfiles + 8 }

func init() { *(*uintptr)(unsafe.Pointer(Xstderr)) = X__stdfiles + 16 }

var (
bss = crt.BSS([0])
bssInit [72]byte
ts  = crt.TS("%s\n\x00")
)
jnml@4670:~/tmp>

I hope you can extract the code for your case from the above mechanically
produced Go code. Note that ccgo uses untrptrs instead of normal pointers
but that should be an easy adjustment, I hope.

-- 

-j

-- 
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] CGO - convert a c.char array to string

2018-08-05 Thread nicolas_boiteux via golang-nuts
it returns :

.\armago_x64.go:19: cannot convert p (type **_Ctype_char) to type uintptr

I am a little lost with this conversion, I do not understand how the 
iterator should work. I hope there was a simple command like GoString to do 
it.


Le dimanche 5 août 2018 12:16:13 UTC+2, Jan Mercl a écrit :
>
> On Sun, Aug 5, 2018 at 12:05 PM nicolas_boiteux via golang-nuts <
> golan...@googlegroups.com > wrote:
>
> > Do you know a standard method to iterate & convert all the argv array in 
> one golang string array ?
>
> Something like (not tested):
>
> var a []string
> for p := argv; *p != nil; p = 
> (**C.char)(unsafe.Pointer(uintptr(p)+unsafe.Sizeof(*p))) {
> a = append(a, C.GoSting(*p))
> }
>
> -- 
>
> -j
>

-- 
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] CGO - convert a c.char array to string

2018-08-05 Thread Jan Mercl
On Sun, Aug 5, 2018 at 12:05 PM nicolas_boiteux via golang-nuts <
golang-nuts@googlegroups.com> wrote:

> Do you know a standard method to iterate & convert all the argv array in
one golang string array ?

Something like (not tested):

var a []string
for p := argv; *p != nil; p =
(**C.char)(unsafe.Pointer(uintptr(p)+unsafe.Sizeof(*p))) {
a = append(a, C.GoSting(*p))
}

-- 

-j

-- 
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] CGO - convert a c.char array to string

2018-08-05 Thread nicolas_boiteux via golang-nuts
Hello

i have a little problem to convert a C char array to a string array in 
golang.

https://community.bistudio.com/wiki/Extensions

func RVExtensionArgs(output *C.char, outputsize C.size_t, input *C.char, 
argv **C.char, argc C.size_t) {
temp := fmt.Sprintf("Hello %s %d %s!", C.GoString(input), argc,  C.
GoString(*argv)

// return to C program, the string
result := C.CString(temp)
defer C.free(unsafe.Pointer(result))
var size = C.strlen(result) + 1
if size > outputsize {
size = outputsize
}
C.memmove(unsafe.Pointer(output), unsafe.Pointer(result), size)
}

I did this code only to print the content of argv for test purpose. This 
code only return the first string of argv array.

Do you know a standard method to iterate & convert all the argv array in 
one golang string array  ?

-- 
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] Streaming (chunked HTTP) to fasthttp.RequestCtx

2018-08-05 Thread Miki Tebeka
Hi,

Since I didn't get an answer on SO 
,
 
though I'll try here :)

I'd like to let client do streaming API and using fasthttp as the backend.
I don't want to expose the `fasthttp.RequestCtx` to the client and don't 
want to get a channel from the client function.

Here's the code I have (the client function is `worker`), when I run it and 
then do `curl -iv http://localhost:8080` it gets stuck. On the server side 
I see 5 `WRITE: ...` prints. Debugging it seems like the server hangs in 
`s.writer.Flush()`

Any ideas how to implement this?

package main


import (
"bufio"
"fmt"
"log"


"github.com/valyala/fasthttp"
)


var (
poem = []string{
"The Road goes ever on and on",
"Down from the door where it began.",
"Now far ahead the Road has gone,",
"And I must follow, if I can,",
"Pursuing it with eager feet,",
"Until it joins some larger way",
"Where many paths and errands meet.",
"And whither then? I cannot say.",
}
)


// Streamer is streaming API
type Streamer interface {
// Write writes bytes to streamer
Write(p []byte) (n int, err error)
// Flush flushes data to the client
Flush() error
// SetStatusCode sets the status code. *Must* be called before Write 
and Flush
SetStatusCode(statusCode int) error
// SetHeader sets a response header. *Must* be called before Write and 
Flush
SetHeader(key string, value interface{}) error
}


// HTTPStreamer implement Streamer with fasthttp
type HTTPStreamer struct {
ctx*fasthttp.RequestCtx
done   chan bool
writer *bufio.Writer
}


// NewHTTPStreamer returns a new HTTPStreamer
func NewHTTPStreamer(ctx *fasthttp.RequestCtx) *HTTPStreamer {
return {
ctx: ctx,
}
}


// Close closes the stream
func (s *HTTPStreamer) Close() {
if s.done != nil {
close(s.done)
}
}


// Write writes bytes to streamer
func (s *HTTPStreamer) Write(p []byte) (n int, err error) {
if s.writer == nil {
s.done = make(chan bool)
ready := make(chan bool)
go func() {
s.ctx.SetBodyStreamWriter(func(w *bufio.Writer) {
s.writer = w
ready <- true // Signal that writer is set
<-s.done  // Wait for stream to be closed
})
}()


<-ready // Wait until writer is set
}


fmt.Printf("WRITE: %s", string(p))
return s.writer.Write(p)
}


// Flush flushes data to the client
func (s *HTTPStreamer) Flush() error {
if s.writer != nil {
return s.writer.Flush()
}


return nil
}


// SetStatusCode sets the status code. *Must* be called before Write and 
Flush
func (s *HTTPStreamer) SetStatusCode(statusCode int) error {
if s.writer != nil {
return fmt.Errorf("Streaming started - can't set status")
}


s.ctx.SetStatusCode(statusCode)
return nil
}


// SetHeader sets a response header. *Must* be called before Write and Flush
// value can be string or []byte
func (s *HTTPStreamer) SetHeader(key string, value interface{}) error {
if s.writer != nil {
return fmt.Errorf("Streaming started - can't set header")
}


switch v := value.(type) {
case string:
s.ctx.Response.Header.Set(key, v)
case []byte:
s.ctx.Response.Header.SetBytesV(key, v)
default:
return fmt.Errorf("Unsupported header value type - %T", value)
}


return nil
}


func worker(s Streamer) {
s.SetStatusCode(201)
s.SetHeader("X-T", "VALUE")
for _, line := range poem {
s.Write([]byte(line + "\n"))
s.Flush()
}
}


func handler(ctx *fasthttp.RequestCtx) {
s := NewHTTPStreamer(ctx)
worker(s)
s.Close()
}


func main() {
srv := {
Handler: handler,
}


if err := srv.ListenAndServe(":8080"); err != nil {
log.Fatal(err)
}
}



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