Your answer is awesome, thank you


在 2014年2月26日星期三 UTC+13上午6:58:27,Carlos Castillo写道:
>
> First of all, if you are presenting code, you should use playground links.
>
>    - You shouldn't be using panic in load, filepath.Walk will return the 
>    error that load returns if the error is not nil, and not filepath.SkipDir: 
>    http://play.golang.org/p/2bu5gWluri
>    - loadPages can panic, or log.Fatal, return the error to code that 
>       handles the error, or deal with the error itself (eg: try another path)
>    - You can store just the processed byte slice in the map, not a 
>    *bytes.Buffer: http://play.golang.org/p/MjSi3dBHDr
>       - If you need an io.Reader type (which your example doesn't), you 
>       can create a bytes.Reader on the []byte instead, which is much more 
>       lightweight, and safer to use
>    - In the handler, with a byte-slice you can use 
>    http.ResponseWriter.Write directly: http://play.golang.org/p/dKM6MZKdas
>       - Although the only thing that can fail is the write to the client 
>       (and so you can't give them an error message), you probably should log 
> the 
>       error from the ResponseWriter
>    - Alternatively to using filepath.Walk, with filepath.Match to check 
>    files, you could use filepath.Glob, to get the list of matching files and 
>    then make your own for-loop.
>       - Upsides
>          - You don't need to write callback code
>          - Probably can fit it all in one function
>       - Downsides:
>          - No recursive traversal into subdirectories
>             - May not be an issue
>          - You don't get a os.FileInfo automatically (to test for dirs, 
>          etc...)
>             - If the user has a directory that matches your pattern, it 
>             might make more sense to return the error from ioutil.ReadFile 
> than to 
>             check and then skip it
>          
> In your code, you are reading the contents of a directory once at startup, 
> and storing the processed contents in memory. This means that you have to 
> restart the program if you want to serve updated or new files, and that the 
> memory for these files is always in use. Neither of these problems is 
> critical, and I have no idea of you specific situation, so you don't need 
> to change your program, but just be mindful of the limitations of the code 
> you have written. Also your code doesn't distinguish the files "1-foo.md" 
> from "2-foo.md" in the map, so the later will overwrite the former. This 
> may have been your intent though...
>
> Finally to answer your initial question, the packages you mention in the 
> subject line work as follows w.r.t. your needs:
>
>    - io defines interfaces that handle streams of bytes (Reader, Writer, 
>    etc...) as well as functions that work generically with types implement 
>    these interfaces (eg: io.Copy)
>    - os defines types and functions that represent operating system 
>    objects/functionality at a low level that is portable across all go 
>    implementations.
>       - *os.File is a type that implements io.Reader, and io.Writer 
>       (among others) which streams bytes to or from a file on disk
>          - It is useful if you don't want to read the whole file into 
>          memory, or are using io.Copy (or some other method) to stream data 
> to/from 
>          the file
>          - It has the downside of being a lower level construct, meaning 
>          data must often be processed in loops (with error checks on each 
>          iteration), and that it must be manually managed (via Close())
>       - io/ioutil provides helper functions for some non-trivial file and 
>    io tasks
>       - ReadFile reads an entire file into memory (as a []byte) in a 
>       single call
>          - It automatically allocates a byte slice of the correct size 
>          (no need to Read + append in a loop)
>          - It automatically closes the file
>          - It returns the first error that prevented it from working (so 
>          you only need a single error check)
>       - bufio provides wrapper types for io.Reader and io.Writer that 
>    buffer the input / output to improve efficiency
>       - The net/http package already buffers data for you (using bufio 
>       itself) so you don't need this package for that
>       - If you are reading a file in one or a few large steps, you 
>       probably don't need it either
>       - buffered input and output add some extra concerns
>       - bufio.Scanner is a nice utility type to efficiently read 
>       independent lines of text from an io.Reader
>    - bytes provides helper functions and types for interacting with byte 
>    slices ([]byte)
>       - bytes.Reader turns a []byte into a io.Reader (as well as an 
>       io.Seeker to rewind)
>       - bytes.Buffer uses []bytes to implement a reader/writer, it is 
>       useful when you want to use code that takes an io.Writer, and store the 
>       results in memory for use later
>       - the strings package provides analogous behaviour for go strings
>    
> On Monday, February 24, 2014 11:20:45 PM UTC-8, Cyru Sol wrote:
>>
>> Hi, I've posted this on reddit and got send here.
>>
>> I'm quite confused as there seems to be multiple redundant ways to solve 
>> my problem (read a file, parse the content, serve it via http).
>> Most people on stackoverflow would use bufio, but I just can't get the 
>> differences between this package and the Buffer type of bytes and just 
>> reading a file with the os methods.
>> Also I don't know when and why I should choose those ways to do it, when 
>> I have the simple, but non-versatile, ioutils.ReadFile.
>>
>> This is how I solved it currently:
>>
>> func loadPage(path string, f os.FileInfo, err error) error {
>>     if err != nil {
>>         panic(err)
>>     }
>>     if !!f.IsDir() {
>>         return nil
>>     }
>>     matched, err := filepath.Match("[0-9]-*.md", f.Name())
>>     if err != nil {
>>         panic(err)
>>     }
>>     if matched {
>>         titleStart := strings.Index(f.Name(), "-") + 1
>>         titleEnd := strings.LastIndex(f.Name(), ".md")
>>         title := strings.ToLower(f.Name()[titleStart:titleEnd])
>>         content, err := ioutil.ReadFile(path)
>>         if err != nil {
>>             panic(err)
>>         }
>>         pages[title] = 
>> bytes.NewBuffer(blackfriday.MarkdownCommon(content))
>>     }
>>     return nil
>> }
>>
>> func loadPages() {
>>     pages = make(map[string]*bytes.Buffer)
>>     err := filepath.Walk(PAGEDIR, loadPage)
>>     if err != nil {
>>         panic(err)
>>     }
>> }
>>
>> Besides replacing the panic calls, what could I do to improve this? I 
>> think there are too many confusing redundant possibilities...
>>
>

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

Reply via email to